<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <title>Client-side API Design Principles</title>
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in §N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/******************************************************************************/
/*                                   Body                                     */
/******************************************************************************/

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;               /* limit line length to 50em for readability   */
		margin: 0 auto;                /* center text within page                     */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag     */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		/* Colors */
		color: black;
		background: white top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		color: white;
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		border-color: #c00;
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
			color: black;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			background: white;
			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;
			background: white;
		}
		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		#toc-nav > a:hover,
		#toc-nav > a:focus {
			background: #f8f8f8;
		}
		#toc-nav > a:not(:hover):not(:focus) {
			color: #707070;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}

		#toc-toggle-inline {
			vertical-align: 0.05em;
			font-size: 80%;
			color: gray;
			color: hsla(203,20%,40%,.7);
			border-style: none;
			background: transparent;
			position: relative;
		}
		#toc-toggle-inline:hover:not(:active),
		#toc-toggle-inline:focus:not(:active) {
			text-shadow: 1px 1px silver;
			top: -1px;
			left: -1px;
		}

		#toc-nav :active {
			color: #C00;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;    /* Inherit the font family. */
		line-height: 1.2;        /* Keep wrapped headings compact */
		hyphens: manual;         /* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		background: transparent;
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#subtitle {
		/* #subtitle is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	 border-left: 0.5em solid #DEF;
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	  padding: .5em;
	  border: thin solid #ddd; border-radius: .5em;
	  margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	  margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	  margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	 margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	 margin-left: -2em;
	}
	dl.switch {
	 padding-left: 2em;
	}
	dl.switch > dt {
	 text-indent: -1.5em;
	 margin-top: 1em;
	}
	dl.switch > dt + dt {
	 margin-top: 0;
	}
	dl.switch > dt::before {
	 content: '\21AA';
	 padding: 0 0.5em 0 0;
	 display: inline-block;
	 width: 1em;
	 text-align: right;
	 line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: medium;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del { color: red;  text-decoration: line-through; }
	ins { color: #080; text-decoration: underline;    }

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		page-break-inside: avoid;
		hyphens: none;
		text-transform: none;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

  /* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		text-decoration: none;
		border-bottom: 1px solid #707070;
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		border-bottom-color: #BBB;
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #C00;
		border-color: #C00;
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	/* For autogen numbers, add
	   .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,    .sidefigure img,    figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #E05252;
		background: #FBE9E9;
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		text-transform: uppercase;
		color: #AE1E1E;
		padding-right: 1em;
		text-transform: uppercase;
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	   or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #E0CB52;
		background: #FCFAEE;
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		text-transform: uppercase;
		color: #827017;
		min-width: 7.5em;
		display: block;
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	   or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52E052;
		background: #E9FBE9;
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary::before,
	details.note > summary > .marker {
		text-transform: uppercase;
		display: block;
		color: hsl(120, 70%, 30%);
	}
	/* Add .note::before { content: "Note"; } for autogen label,
	   or use class="marker" to mark up the label in source. */

	details.note > summary {
		display: block;
		color: hsl(120, 70%, 30%);
	}
	details.note[open] > summary {
		border-bottom: 1px silver solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		background: #EEE;
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-style: none solid;
		background: #FFEECC;
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement > .marker {
		color: #B35F00;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: #fdd;
		color: red;
		font-weight: bold;
		padding: .75em 1em;
		border: thick red;
		border-style: solid;
		border-radius: 1em;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 1em;
		right: 1em;
		bottom: 1em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #DEF;
		margin: 1.2em 0;
		border-left: 0.5em solid #8CCBF2;
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def           td.footnote {
		padding-top: 0.6em;
	}
	table.def           td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		 <table class="data"> highlights structural relationships in a table
		 when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		 Use class="complex data" for particularly complicated tables --
		 (This will draw more lines: busier, but clearer.)

		 Use class="long" on table cells with paragraph-like contents
		 (This will adjust text alignment accordingly.)
		 Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
	 vertical-align: baseline;
	 text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		border-color: #3980B5;
		border-bottom-width: 3px !important;
		margin-bottom: 0px !important;
	}
	.toc a:visited {
		border-color: #054572;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
		line-height: 1.1rem; /* consistent spacing */
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li             { font-weight: bold;   }
	.toc > li li          { font-weight: normal; }
	.toc > li li li       { font-size:   95%;    }
	.toc > li li li li    { font-size:   90%;    }
	.toc > li li li li .secno { font-size: 85%; }
	.toc > li li li li li { font-size:   85%;    }
	.toc > li li li li li .secno { font-size: 100%; }

	/* @supports not (display:grid) { */
		.toc > li             { margin: 1.5rem 0;    }
		.toc > li li          { margin: 0.3rem 0;    }
		.toc > li li li       { margin-left: 2rem;   }

		/* Section numbers in a column of their own */
		.toc .secno {
			float: left;
			width: 4rem;
			white-space: nowrap;
		}

		.toc li {
			clear: both;
		}

		:not(li) > .toc              { margin-left:  5rem; }
		.toc .secno                  { margin-left: -5rem; }
		.toc > li li li .secno       { margin-left: -7rem; }
		.toc > li li li li .secno    { margin-left: -9rem; }
		.toc > li li li li li .secno { margin-left: -11rem; }

		/* Tighten up indentation in narrow ToCs */
		@media (max-width: 30em) {
			:not(li) > .toc              { margin-left:  4rem; }
			.toc .secno                  { margin-left: -4rem; }
			.toc > li li li              { margin-left:  1rem; }
			.toc > li li li .secno       { margin-left: -5rem; }
			.toc > li li li li .secno    { margin-left: -6rem; }
			.toc > li li li li li .secno { margin-left: -7rem; }
		}
	/* } */

	@supports (display:grid) and (display:contents) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			   comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
		}
		#toc .content:hover {
			background: rgba(75%, 75%, 75%, .25);
			border-bottom: 3px solid #054572;
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index       { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li    { margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em }
	ul.index dl    { margin-top: 0; }
	ul.index dt    { margin: .2em 0 .2em 20px;}
	ul.index dd    { margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		background: #f7f8f9;
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}

/******************************************************************************/
/*                                    Legacy                                  */
/******************************************************************************/

	/* This rule is inherited from past style sheets. No idea what it's for. */
	.hide { display: none }



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge {
		/* Magic to create good table positioning:
		   "content column" is 50ems wide at max; less on smaller screens.
		   Extra space (after ToC + content) is empty on the right.

		   1. When table < content column, centers table in column.
		   2. When content < table < available, left-aligns.
		   3. When table > available, fills available + scroll bar.
		*/ 
		display: grid;
		grid-template-columns: minmax(0, 50em);
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style>
    table.data {
        text-align: left;
        font-size: small;
    }
</style>
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-selflinks */

.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: gray;
    color: white;
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: black;
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: #005a9c;
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
<style>/* style-dfn-panel */

.dfn-panel {
    position: absolute;
    z-index: 35;
    height: auto;
    width: -webkit-fit-content;
    width: fit-content;
    max-width: 300px;
    max-height: 500px;
    overflow: auto;
    padding: 0.5em 0.75em;
    font: small Helvetica Neue, sans-serif, Droid Sans Fallback;
    background: #DDDDDD;
    color: black;
    border: outset 0.2em;
}
.dfn-panel:not(.on) { display: none; }
.dfn-panel * { margin: 0; padding: 0; text-indent: 0; }
.dfn-panel > b { display: block; }
.dfn-panel a { color: black; }
.dfn-panel a:not(:hover) { text-decoration: none !important; border-bottom: none !important; }
.dfn-panel > b + b { margin-top: 0.25em; }
.dfn-panel ul { padding: 0; }
.dfn-panel li { list-style: inside; }
.dfn-panel.activated {
    display: inline-block;
    position: fixed;
    left: .5em;
    bottom: 2em;
    margin: 0 auto;
    max-width: calc(100vw - 1.5em - .4em - .5em);
    max-height: 30vh;
}

.dfn-paneled { cursor: pointer; }
</style>
<style>/* style-syntax-highlighting */

.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">Client-side API Design Principles</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">A Collection of Interesting Ideas, <time class="dt-updated" datetime="1970-01-01">1 January 1970</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt class="editor">Editors:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:travil@microsoft.com">Travis Leithead</a> (<span class="p-org org">Microsoft</span>)
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-url url" href="https://sangwhan.com">Sangwhan Moon</a> (<span class="p-org org">Invited Expert</span>)
     <dt class="editor">Former Editor:
     <dd class="editor p-author h-card vcard"><a class="p-name fn u-url url" href="https://domenic.me/">Domenic Denicola</a> (<a class="p-org org" href="https://www.google.com/">Google</a>) <a class="u-email email" href="mailto:d@domenic.me">d@domenic.me</a>
     <dt>By:
     <dd><a href="https://www.w3.org/2001/tag/">Members of the TAG</a>, past and present
     <dt>Participate:
     <dd><a href="https://github.com/w3ctag/design-principles">GitHub w3ctag/design-principles</a> (<a href="https://github.com/w3ctag/design-principles/issues/new">file an issue</a>; <a href="https://github.com/w3ctag/design-principles/issues?state=open">open issues</a>)
     <dd>
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <p class="copyright" data-fill-with="copyright"><a href="http://creativecommons.org/publicdomain/zero/1.0/" rel="license"><img alt="CC0" src="https://licensebuttons.net/p/zero/1.0/80x15.png"></a> To the extent possible under law, the editors have waived all copyright
and related or neighboring rights to this work.
In addition, as of 1 January 1970,
the editors have made this specification available under the <a href="http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0" rel="license">Open Web Foundation Agreement Version 1.0</a>,
which is available at http://www.openwebfoundation.org/legal/the-owf-1-0-agreements/owfa-1-0.
Parts of this work may be from another specification document.  If so, those parts are instead covered by the license of that specification document. </p>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>This document contains a small-but-growing set of design principles collected by the W3C TAG while <a href="https://github.com/w3ctag/spec-reviews/">reviewing</a> specifications.</p>
  </div>
  <div data-fill-with="at-risk"></div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li>
     <a href="#js"><span class="secno">1</span> <span class="content">JavaScript Language</span></a>
     <ol class="toc">
      <li><a href="#js-only"><span class="secno">1.1</span> <span class="content">Web APIs are for JavaScript</span></a>
      <li><a href="#js-rtc"><span class="secno">1.2</span> <span class="content">Preserve run-to-completion semantics</span></a>
      <li><a href="#js-gc"><span class="secno">1.3</span> <span class="content">Do not expose garbage collection</span></a>
     </ol>
    <li>
     <a href="#api-surface"><span class="secno">2</span> <span class="content">API Surface Concerns</span></a>
     <ol class="toc">
      <li><a href="#naming-is-hard"><span class="secno">2.1</span> <span class="content">Naming things</span></a>
      <li><a href="#feature-detect"><span class="secno">2.2</span> <span class="content">New features should be detectable</span></a>
      <li><a href="#attributes-like-data"><span class="secno">2.3</span> <span class="content">Attributes should behave like data properties</span></a>
      <li><a href="#live-vs-static"><span class="secno">2.4</span> <span class="content">Consider whether objects should be live or static</span></a>
      <li><a href="#casing-rules"><span class="secno">2.5</span> <span class="content">Use casing rules consistent with existing APIs</span></a>
      <li><a href="#prefer-dict-to-bool"><span class="secno">2.6</span> <span class="content">Prefer dictionary parameters over boolean parameters or other unreadable parameters</span></a>
      <li><a href="#constructors"><span class="secno">2.7</span> <span class="content">Classes should have constructors when possible</span></a>
      <li><a href="#promises"><span class="secno">2.8</span> <span class="content">Design asynchronous APIs using Promises</span></a>
      <li><a href="#aborting"><span class="secno">2.9</span> <span class="content">Cancel asynchronous APIs/operations using AbortSignal</span></a>
      <li><a href="#secure-context"><span class="secno">2.10</span> <span class="content">Consider limiting new features to secure contexts</span></a>
      <li><a href="#string-constants"><span class="secno">2.11</span> <span class="content">Constants, enums, and bitmasks</span></a>
     </ol>
    <li>
     <a href="#event-design"><span class="secno">3</span> <span class="content">Event Design</span></a>
     <ol class="toc">
      <li><a href="#one-time-events"><span class="secno">3.1</span> <span class="content">Use promises for one time events</span></a>
      <li><a href="#promises-and-events"><span class="secno">3.2</span> <span class="content">Events should fire before Promises resolve</span></a>
      <li><a href="#dont-invent-event-like"><span class="secno">3.3</span> <span class="content">Don’t invent your own event listener-like infrastructure</span></a>
      <li><a href="#always-add-event-handlers"><span class="secno">3.4</span> <span class="content">Always add event handler attributes</span></a>
      <li><a href="#events-are-for-notification"><span class="secno">3.5</span> <span class="content">Events are for notification</span></a>
      <li><a href="#favor-asynchronous-events"><span class="secno">3.6</span> <span class="content">Favor asynchronous events</span></a>
      <li><a href="#state-and-subclassing"><span class="secno">3.7</span> <span class="content">State and <code class="idl"><span>Event</span></code> subclasses</span></a>
      <li><a href="#events-vs-observers"><span class="secno">3.8</span> <span class="content">How to decide between Events and Observers</span></a>
     </ol>
    <li>
     <a href="#types-and-units"><span class="secno">4</span> <span class="content">Types and Units</span></a>
     <ol class="toc">
      <li><a href="#numeric-types"><span class="secno">4.1</span> <span class="content">Use numeric types appropriately</span></a>
      <li><a href="#milliseconds"><span class="secno">4.2</span> <span class="content">Use milliseconds for time measurement</span></a>
      <li><a href="#times-and-dates"><span class="secno">4.3</span> <span class="content">Use the appropriate type to represent times and dates</span></a>
      <li><a href="#error-types"><span class="secno">4.4</span> <span class="content">Use Error or DOMException for errors</span></a>
     </ol>
    <li>
     <a href="#device-apis"><span class="secno">5</span> <span class="content">OS and Device Wrapper APIs</span></a>
     <ol class="toc">
      <li><a href="#device-ids"><span class="secno">5.1</span> <span class="content">Use care when exposing device identifiers</span></a>
      <li><a href="#wrapper-apis"><span class="secno">5.2</span> <span class="content">Native APIs don’t typically translate well to the web</span></a>
     </ol>
    <li>
     <a href="#other-considerations"><span class="secno">6</span> <span class="content">Other API Design Considerations</span></a>
     <ol class="toc">
      <li><a href="#design-resources"><span class="secno">6.1</span> <span class="content">Privacy, Security, Accessibility, and Internationalization</span></a>
      <li><a href="#polyfills"><span class="secno">6.2</span> <span class="content">Polyfills</span></a>
     </ol>
    <li>
     <a href="#spec-writing"><span class="secno">7</span> <span class="content">Writing good specifications</span></a>
     <ol class="toc">
      <li><a href="#writing-resources"><span class="secno">7.1</span> <span class="content">Other resources</span></a>
      <li><a href="#algorithms"><span class="secno">7.2</span> <span class="content">Specify clearly enough so that algorithms are unambiguous</span></a>
     </ol>
    <li><a href="#conformance"><span class="secno"></span> <span class="content"> Conformance</span></a>
    <li>
     <a href="#index"><span class="secno"></span> <span class="content">Index</span></a>
     <ol class="toc">
      <li><a href="#index-defined-here"><span class="secno"></span> <span class="content">Terms defined by this specification</span></a>
      <li><a href="#index-defined-elsewhere"><span class="secno"></span> <span class="content">Terms defined by reference</span></a>
     </ol>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#normative"><span class="secno"></span> <span class="content">Normative References</span></a>
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="js"><span class="secno">1. </span><span class="content">JavaScript Language</span><a class="self-link" href="#js"></a></h2>
   <h3 class="heading settled" data-level="1.1" id="js-only"><span class="secno">1.1. </span><span class="content">Web APIs are for JavaScript</span><a class="self-link" href="#js-only"></a></h3>
   <p>The language that web APIs are meant to be used in, and specified for, is JavaScript (also known as <a data-link-type="biblio" href="#biblio-ecmascript">[ECMASCRIPT]</a>). They are not language-agnostic, and are not meant to be.</p>
   <p>This is sometimes a confusing point because <a data-link-type="biblio" href="#biblio-webidl">[WEBIDL]</a> descended from the language-agnostic OMG IDL
(and at one point, included "Java Bindings"). Even today, the structure of the document contains a
confusing and redundant division between the "Interface definition language" and the "ECMAScript
binding". Rest assured that this division is simply a historical artifact of document structure,
and does not imply anything about the intent of Web IDL in general. The only reason it remains is
that nobody has taken the time to eradicate it.</p>
   <p>As such, when designing your APIs, your primary concern should be with the interface you present to
JavaScript developers. You can freely rely upon language-specific semantics and conventions, with
no need to keep things generalized.</p>
   <h3 class="heading settled" data-level="1.2" id="js-rtc"><span class="secno">1.2. </span><span class="content">Preserve run-to-completion semantics</span><a class="self-link" href="#js-rtc"></a></h3>
   <p>Web APIs are essentially vehicles for extruding C++- (or Rust-) authored capabilities into the
JavaScript code that developers write. As such, it’s important to respect the invariants that are
in play in normal JavaScript code. One of the most important of these is <em>run-to-completion
semantics</em>: wherein each turn of the JavaScript event loop is processed completely before
returning control to the user agent.</p>
   <p>In particular, this means that JavaScript functions cannot be preempted mid-execution, and thus
that any data observed within the function will stay constant as long as that function is active.
This is not the case in other languages, which allow data races via multithreading or other
techniques—a C function can be preempted at any time, with the bindings it has access to changing
values from one line to the next.</p>
   <p>This no-data-races invariant is extensively relied upon in JavaScript programs. As such, the
invariant must never be violated—even by web APIs, which are often implemented in languages that <em>do</em> allow data races. Although the user agent may be using threads or other techniques to
modify state <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/infrastructure.html#in-parallel" id="ref-for-in-parallel">in parallel</a>, web APIs must never expose such changing state directly to
developers. Instead, they should <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-task" id="ref-for-queue-a-task">queue a task</a> to modify author-observable state (such as an
object property).</p>
   <h3 class="heading settled" data-level="1.3" id="js-gc"><span class="secno">1.3. </span><span class="content">Do not expose garbage collection</span><a class="self-link" href="#js-gc"></a></h3>
   <p>Web APIs should not expose a way for author code to deduce when/if garbage collection of JavaScript
objects has run.</p>
   <p>Although some APIs may expose garbage collection, such as some implementations of <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#ref-for-concept-getelementsbytagname" id="ref-for-ref-for-concept-getelementsbytagname">getElementsByTagName</a></code>, and the JavaScript <a href="https://github.com/tc39/proposal-weakrefs">WeakRefs proposal</a> (which has multiple
implementer support), API designers are strongly encouraged to avoid points in their own APIs that
depend on this timing.</p>
   <p>The reason for this is somewhat subtle. The more that Web API semantics are affected by garbage
collection timing (or whether objects are collected at all), the more programs will be affected by
changes in this timing. But user agents differ significantly in both the timing of garbage
collection and whether certain objects are collected at all, which means the resulting code will be
non-interoperable. Worse, according to the usual rules of game theory as applied to browsers, this
kind of scenario could force other user agents to copy the garbage collection timing of the
original in order to create interoperability. This would cause current garbage collection
strategies to ossify, preventing improvement in one of the most dynamic areas of JavaScript
virtual machine technology.</p>
   <p>In particular, this means that you shouldn’t expose any API that acts as a weak reference, e.g. with a
property that becomes <code class="highlight"><c- kc>null</c-></code> once garbage collection runs. Such freeing of
memory should be entirely deterministic.</p>
   <p>For example, currently, <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#ref-for-concept-getelementsbytagname" id="ref-for-ref-for-concept-getelementsbytagname①">getElementsByTagName</a></code> permits reusing the <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#htmlcollection" id="ref-for-htmlcollection">HTMLCollection</a></code> which it creates, when it’s called with the same receiver and tag name. In practice, engines reuse
the output if it has not been garbage collected. This creates behavior which differs based on the
details of garbage collection, which is strongly discouraged. If <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#ref-for-concept-getelementsbytagname" id="ref-for-ref-for-concept-getelementsbytagname②">getElementsByTagName</a></code> were designed today, the advice to the specification authors would be to either reliably reuse
the output, or to produce a new <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#htmlcollection" id="ref-for-htmlcollection①">HTMLCollection</a></code> each time it’s invoked.</p>
   <p>The case of <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#ref-for-concept-getelementsbytagname" id="ref-for-ref-for-concept-getelementsbytagname③">getElementsByTagName</a></code> is particularly insidious because nothing about
the API visibly relates to garbage collection details. By contrast, special APIs for this particular
purpose such as <code>WeakRef</code> and <code>FinalizationGroup</code> have their GC interaction as a specific part of
their contract with the developer.</p>
   <h2 class="heading settled" data-level="2" id="api-surface"><span class="secno">2. </span><span class="content">API Surface Concerns</span><a class="self-link" href="#api-surface"></a></h2>
   <h3 class="heading settled" data-level="2.1" id="naming-is-hard"><span class="secno">2.1. </span><span class="content">Naming things</span><a class="self-link" href="#naming-is-hard"></a></h3>
   <p>Naming is hard! We would all like a silver-bullet for naming APIs...</p>
   <p>Names take meaning from:</p>
   <ul>
    <li data-md>
     <p>signposting (the name itself)</p>
    <li data-md>
     <p>use (how people come to understand the name over time)</p>
    <li data-md>
     <p>context (the object on the left-hand side, for example)</p>
   </ul>
   <p>Consistency is a good principle that helps to create a platform that users can navigate intuitively
and by name association.</p>
   <p>Please consult widely on names in your APIs.</p>
   <p>Boolean properties, options, or API parameters which are asking a question about
their argument <em>should not</em> be prefixed with <code>is</code>, while methods
that serve the same purpose, given that it has no side effects, <em>should</em> be
prefixed with <code>is</code> to be consistent with the rest of the platform.</p>
   <p>The name should not be directly associated with a brand or specific revision of
the underlying technology whenever possible; technology becomes obsolete, but
since removing APIs from the web is difficult, naming should be generic and
future-proof whenever possible.</p>
   <h3 class="heading settled" data-level="2.2" id="feature-detect"><span class="secno">2.2. </span><span class="content">New features should be detectable</span><a class="self-link" href="#feature-detect"></a></h3>
   <p>The existence of new features should generally be detectable,
so that web content can act appropriately whether the feature is present or not.
This applies both to features that
are not present because they are not implemented,
and to features that may not be present in a particular configuration
(ranging from features that are present only on particular platforms
to features that are
only available in secure contexts).</p>
   <p>It should generally be indistinguishable why a feature is unavailable,
so that feature detection code written for one case of unavailability
(e.g., the feature not being implemented yet in some browsers)
also works in other cases
(e.g., a library being used in a non-secure context when
the feature is limited to secure contexts).</p>
   <p>Detection should always be possible from script,
but in some cases the feature should also be detectable
in the language where it is used
(such as <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-conditional-3/#at-ruledef-supports" id="ref-for-at-ruledef-supports">@supports</a> in CSS).</p>
   <h3 class="heading settled" data-level="2.3" id="attributes-like-data"><span class="secno">2.3. </span><span class="content">Attributes should behave like data properties</span><a class="self-link" href="#attributes-like-data"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-webidl">[WEBIDL]</a> attributes are reified in JavaScript as accessor properties, i.e. properties with
separate getter and setter functions which can react independently. This is in contrast to the
"default" style of JavaScript properties, data properties, which do not have configurable behavior
but instead can simply be set and retrieved, or optionally marked read-only so that they cannot be
set.</p>
   <p>Data property semantics are what are generally expected by JavaScript developers when interfacing
with objects. As such, although getters and setters allow infinite customizability when defining
your Web IDL attributes, you should endeavor to make the resulting accessor properties behave as
much like a data property as possible. Specific guidance in this regard includes:</p>
   <ul>
    <li data-md>
     <p>Getters must not have any (observable) side effects.</p>
    <li data-md>
     <p>Getters should not perform any expensive operations. (A notable failure of the platform in this
regard is getters like <code class="highlight">offsetTop</code> performing layout; do not repeat this mistake.)</p>
    <li data-md>
     <p>Ensure that your attribute’s getter returns the same object each time it is called, until some
occurrence in another part of the system causes a logical "reset" of the property’s value. In
particular, <code class="highlight">obj<c- p>.</c->attribute <c- o>===</c-> obj<c- p>.</c->attribute</code> must always hold, and so returning a
new value from the getter each time is not allowed.</p>
    <li data-md>
     <p>Whenever possible, preserve values given to the setter for return from the getter. That is,
given <code class="highlight">obj<c- p>.</c->attribute <c- o>=</c-> x</code>, a subsequent <code class="highlight">obj<c- p>.</c->attribute <c- o>===</c-> x</code> should be
true. (This will not always be the case, e.g. if a normalization or type conversion step is
necessary, but should be held as a goal for normal code paths.)</p>
   </ul>
   <h3 class="heading settled" data-level="2.4" id="live-vs-static"><span class="secno">2.4. </span><span class="content">Consider whether objects should be live or static</span><a class="self-link" href="#live-vs-static"></a></h3>
   <p>Objects returned from functions, attribute getters, etc.,
can either be live or static.
A <dfn data-dfn-type="dfn" data-export id="live-object">live object<a class="self-link" href="#live-object"></a></dfn> is one that continues to reflect
changes made after it was returned to the caller.
A <dfn data-dfn-type="dfn" data-export id="static-object">static object<a class="self-link" href="#static-object"></a></dfn> is one that reflects
the state at the time it was returned.</p>
   <p>Objects that are the way state is mutated are generally live.
For example, DOM nodes are returned as live objects,
since they are the API through which attributes are set and other changes
to the DOM are made.
They also reflect changes to the DOM made in other ways
(such as through user interaction with forms).</p>
   <p>Objects that represent a collection
that might change over time
(and that are not the way state is mutated)
should generally be returned as static objects.
This is because it is confusing to users of the API when
a collection changes while being iterated.
Because of this,
it is generally considered a mistake that methods like <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname" id="ref-for-dom-document-getelementsbytagname">getElementsByTagName()</a></code> return live objects; <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall" id="ref-for-dom-parentnode-queryselectorall">querySelectorAll()</a></code> was made to return static objects
as a result of this experience.
On the other hand, even though <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#urlsearchparams" id="ref-for-urlsearchparams">URLSearchParams</a></code> represents a collection,
it should be live because the collection is mutated through that object.</p>
   <p class="note" role="note"><span>Note:</span> It’s possible that some of this advice should be reconsidered
for <a data-link-type="dfn" href="https://heycam.github.io/webidl/#dfn-maplike" id="ref-for-dfn-maplike">maplike</a> and <a data-link-type="dfn" href="https://heycam.github.io/webidl/#dfn-setlike" id="ref-for-dfn-setlike">setlike</a> types,
where iterators have reasonable behavior
for mutation that happens during iteration.
This point likely needs further discussion,
and perhaps further experience of use of these types.</p>
   <p>It’s also worth considering the implications of having
live versus static objects for the speed of implementations of the API.
When the data needed by an object are expensive to compute up-front,
there is an advantage for that object to be live so that the results
can be computed lazily, such as for <code class="idl"><a data-link-type="idl" href="https://drafts.csswg.org/cssom-1/#dom-window-getcomputedstyle" id="ref-for-dom-window-getcomputedstyle">getComputedStyle()</a></code>.
On the other hand,
if the data needed by an object are expensive to keep up-to-date,
such as for the <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#nodelist" id="ref-for-nodelist">NodeList</a></code> returned from <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall" id="ref-for-dom-parentnode-queryselectorall①">querySelectorAll()</a></code>,
then providing a static object avoids
having to keep the object updated until it is garbage collected
(which may be substantially after its last use).</p>
   <p>Likewise, the choice of live versus static objects
can influence the memory use of an API.
If each call of a method returns a new static object,
and the objects are large,
then substantial amounts of memory can be wasted
until the next garbage collection.</p>
   <p>The choice of whether an object is live or static may also
influence whether it should be returned
from an attribute getter or from a method.
See <a href="#attributes-like-data">§ 2.3 Attributes should behave like data properties</a>.
In particular,
if a result that changes frequently is returned as a static object,
it should probably be returned from a method rather than an attribute getter.</p>
   <h3 class="heading settled" data-level="2.5" id="casing-rules"><span class="secno">2.5. </span><span class="content">Use casing rules consistent with existing APIs</span><a class="self-link" href="#casing-rules"></a></h3>
   <p>Although they haven’t always been uniformly followed, through the history of web platform API
design, the following rules have emerged:</p>
   <table class="data complex">
    <thead>
     <tr>
      <th>
      <th>Casing rule
      <th>Examples
    <tbody>
     <tr>
      <th>Methods and properties<br>(Web IDL attributes, operations, and dictionary keys)
      <td>Camel case
      <td><code class="highlight">document<c- p>.</c->createAttribute<c- p>()</c-></code><br> <code class="highlight">document<c- p>.</c->compatMode</code>
     <tr>
      <th>Classes and mixins<br>(Web IDL interfaces)
      <td>Pascal case
      <td><code class="highlight">NamedNodeMap</code><br> <code class="highlight">NonElementParentNode</code>
     <tr>
      <th>Initialisms in APIs
      <td>All caps, except when the first word in a method or property
      <td><code class="highlight">HTMLCollection</code><br> <code class="highlight">element<c- p>.</c->innerHTML</code><br> <code class="highlight">document<c- p>.</c->bgColor</code>
     <tr>
      <th>Repeated initialisms in APIs
      <td>Follow the same rule
      <td><code class="highlight">HTMLHRElement</code><br> <code class="highlight">RTCDTMFSender</code><br> 
     <tr>
      <th>The abbreviation of "identity"
      <td><code class="highlight">Id</code>, except when the first word in a method or property
      <td><code class="highlight">node<c- p>.</c->getElementById<c- p>()</c-></code><br> <code class="highlight">event<c- p>.</c->pointerId</code><br> <code class="highlight">credential<c- p>.</c->id</code>
     <tr>
      <th>Enumeration values
      <td>Lowercase, dash-delimited
      <td><code class="highlight"><c- u>"no-referrer-when-downgrade"</c-></code>
     <tr>
      <th>Events
      <td>Lowercase, concatenated
      <td><code>autocompleteerror</code><br> <code>languagechange</code>
     <tr>
      <th>HTML elements and attributes
      <td>Lowercase, concatenated
      <td><code class="highlight"><c- p>&lt;</c-><c- f>figcaption</c-><c- p>></c-></code><br> <code class="highlight"><c- p>&lt;</c-><c- f>textarea</c-> <c- e>maxlength</c-><c- p>></c-></code>
     <tr>
      <th>JSON keys
      <td>Lowercase, underscore-delimited
      <td><code class="highlight">manifest<c- p>.</c->short_name</code>
   </table>
   <div class="non-normative">
     Note that in particular, when a HTML attribute is <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflect" id="ref-for-reflect">reflected</a> as a property, the attribute
and property’s casings will not necessarily match. For example, the HTML attribute <code><a data-link-type="element-sub" href="https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-ismap" id="ref-for-attr-img-ismap">ismap</a></code> on <code><a data-link-type="element" href="https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element" id="ref-for-the-img-element">img</a></code> elements is <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflect" id="ref-for-reflect①">reflected</a> as the <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-ismap" id="ref-for-dom-img-ismap">isMap</a></code> property on <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/embedded-content.html#htmlimageelement" id="ref-for-htmlimageelement">HTMLImageElement</a></code>. 
    <p>The rules for JSON keys are meant to apply to specific JSON file formats sent over HTTP
or stored on disk, and don’t apply to the general notion of JavaScript object keys.</p>
    <p>Repeated initialisms are particularly non-uniform throughout the platform. Infamous historical
examples that violate the above rules are <code class="idl"><a data-link-type="idl" href="https://xhr.spec.whatwg.org/#xmlhttprequest" id="ref-for-xmlhttprequest">XMLHttpRequest</a></code> and <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/semantics.html#htmlhtmlelement" id="ref-for-htmlhtmlelement">HTMLHtmlElement</a></code>. Do not follow their example; instead always capitalize your
initialisms, even if they are repeated.</p>
   </div>
   <h3 class="heading settled" data-level="2.6" id="prefer-dict-to-bool"><span class="secno">2.6. </span><span class="content">Prefer dictionary parameters over boolean parameters or other unreadable parameters</span><a class="self-link" href="#prefer-dict-to-bool"></a></h3>
   <p>APIs should generally prefer dictionary parameters
(with named booleans in the dictionary)
over boolean parameters.
This makes the code that calls the API <a href="https://ariya.io/2011/08/hall-of-api-shame-boolean-trap">much more readable</a>.
It also makes the API more extensible in the future,
particularly if multiple booleans are needed.</p>
   <p class="example" id="example-44c12439"><a class="self-link" href="#example-44c12439"></a>For example, <code class="highlight"><c- k>new</c-> Event<c- p>(</c-><c- u>"exampleevent"</c-><c- p>,</c-> <c- p>{</c-> bubbles<c- o>:</c-> <c- kc>true</c-><c- p>,</c-> cancelable<c- o>:</c-> <c- kc>false</c-><c- p>})</c-></code> is much more readable than <code class="highlight"><c- k>new</c-> Event<c- p>(</c-><c- u>"exampleevent"</c-><c- p>,</c-> <c- kc>true</c-><c- p>,</c-> <c- kc>false</c-><c- p>)</c-></code>. </p>
   <p>Furthermore,
the booleans in dictionaries need to be designed so that they all default to false.
If booleans default to true, then <a href="https://lists.w3.org/Archives/Public/public-script-coord/2013OctDec/0302.html">users of the API will find unexpected JavaScript behavior</a> since <code class="highlight"><c- p>{</c-> passive<c- o>:</c-> <c- kc>false</c-> <c- p>}</c-></code> and <code class="highlight"><c- p>{</c-> passive<c- o>:</c-> <c- kc>undefined</c-> <c- p>}</c-></code> will produce different results.
But at the same time, it’s important to avoid naming booleans in negative ways,
because then code will have confusing double-negatives.
These pieces of advice may sometimes conflict,
but the conflict can be avoided by using opposite words without negatives,
such as “repeat” versus “once”,
“isolate” versus “connect”,
or “private” versus “public”.</p>
   <p>Likewise, APIs should use dictionary parameters to avoid other cases
of difficult to understand sequences of parameters.
For example, <code class="highlight">window<c- p>.</c->scrollBy<c- p>({</c-> left<c- o>:</c-> <c- mi>50</c-><c- p>,</c-> top<c- o>:</c-> <c- mi>0</c-> <c- p>})</c-></code> is more readable than <code class="highlight">window<c- p>.</c->scrollBy<c- p>(</c-><c- mi>50</c-><c- p>,</c-> <c- mi>0</c-><c- p>)</c-></code>.</p>
   <h3 class="heading settled" data-level="2.7" id="constructors"><span class="secno">2.7. </span><span class="content">Classes should have constructors when possible</span><a class="self-link" href="#constructors"></a></h3>
   <p>By default, <a data-link-type="biblio" href="#biblio-webidl">[WEBIDL]</a> interfaces are reified in JavaScript as "non-constructible" classes: trying
to create instances of them using the normal pattern in JavaScript, <code>new X()</code>, will throw a <code class="idl"><a data-link-type="idl" href="https://heycam.github.io/webidl/#exceptiondef-typeerror" id="ref-for-exceptiondef-typeerror">TypeError</a></code>. This is a poor experience for JavaScript developers, and doesn’t match the design of
most of the JavaScript standard library or of the classes JavaScript developers themselves create.</p>
   <p>From a naive perspective, it’s not even coherent: how can instances of this thing ever exist, if
they can’t be constructed? The answer is that the platform has magic powers: it can create instances
of Web IDL-derived classes without ever actually calling their constructor.</p>
   <p>You should strive to reduce such magic in designing your own APIs, and give them constructors which
allow JavaScript developers to create them, just like the platform does. This means adding an
appropriate [<code class="idl"><a data-link-type="idl" href="https://heycam.github.io/webidl/#Constructor" id="ref-for-Constructor">Constructor</a></code>] extended attribute to your interface, and defining the algorithm for
creating new instances of your class.</p>
   <p>Apart from reducing the magic in the platform, adding constructors allows JavaScript developers to
create instances of the class for their own purposes, such as testing, mocking, or interfacing with
third-party libraries which accept instances of that class. Additionally, because of how
JavaScript’s class design works, it is only possible to create a subclass of the class if it is
constructible.</p>
   <p>Sometimes this isn’t the right answer: for example, some objects essentially wrap handles to
privileged resources, and it isn’t reasonable to create some representation of that privileged
resource in JavaScript so that you can pass it to the constructor. Or the object’s lifecycle needs
to be very carefully controlled, so that creating new ones is only possible through privileged
operations. Or the interface represents an abstract base class for which it doesn’t make sense to
construct an instance, or create an author-defined subclass. But cases like these should be the
exception, not the norm.</p>
   <p class="example" id="example-6f8cdca8"><a class="self-link" href="#example-6f8cdca8"></a>The <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#event" id="ref-for-event">Event</a></code> class, and all its derived interfaces, are constructible. This
allows JavaScript developers to synthesize instances of them, which can be useful in testing or
shimming scenarios. For example, a library designed for <code class="idl"><a data-link-type="idl" href="https://www.w3.org/TR/uievents/#mouseevent" id="ref-for-mouseevent">MouseEvent</a></code> instances can still be used
by another library that accepts as input <code class="idl"><a data-link-type="idl" href="https://w3c.github.io/touch-events/#idl-def-touchevent" id="ref-for-idl-def-touchevent">TouchEvent</a></code> instances, by writing a small bit of adapter
code that creates synthetic <code class="idl"><a data-link-type="idl" href="https://www.w3.org/TR/uievents/#mouseevent" id="ref-for-mouseevent①">MouseEvent</a></code>s.</p>
   <p class="example" id="example-520732fa"><a class="self-link" href="#example-520732fa"></a>The <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#domtokenlist" id="ref-for-domtokenlist">DOMTokenList</a></code> class is, very unfortunately, <a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=27114">not constructible</a>. This prevents the
creation of <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element" id="ref-for-custom-element">custom elements</a> that expose their token list attributes as <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#domtokenlist" id="ref-for-domtokenlist①">DOMTokenList</a></code>s.</p>
   <p class="example" id="example-de08c31c"><a class="self-link" href="#example-de08c31c"></a>No HTML elements are constructible. This is largely due to some unfortunate
design decisions that <a href="https://github.com/whatwg/html/issues/896">would take some effort to
work around</a>. In the meantime, for the purposes of the <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/custom-elements.html#customized-built-in-element" id="ref-for-customized-built-in-element">customized built-in elements</a> feature, they have been made subclassable through a specifically-designed one-off solution: the
[<code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor" id="ref-for-htmlconstructor">HTMLConstructor</a></code>] extended attribute.</p>
   <p class="example" id="example-4d1db045"><a class="self-link" href="#example-4d1db045"></a>The <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/window-object.html#window" id="ref-for-window">Window</a></code> class is not constructible, because creating a new window is a
privileged operation with significant side effects. Instead, the <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/window-object.html#dom-open" id="ref-for-dom-open">window.open()</a></code> method is used to create new windows.</p>
   <p class="example" id="example-38c742ca"><a class="self-link" href="#example-38c742ca"></a>The <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#imagebitmap" id="ref-for-imagebitmap">ImageBitmap</a></code> class is not constructible, as it represents an immutable,
ready-to-paint bitmap image, and the process of getting it ready to paint must be done
asynchronously. Instead, the <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#dom-createimagebitmap" id="ref-for-dom-createimagebitmap">createImageBitmap()</a></code> method is used to create it.</p>
   <p class="example" id="example-09c8f087"><a class="self-link" href="#example-09c8f087"></a>Several non-constructible classes, like <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/system-state.html#navigator" id="ref-for-navigator">Navigator</a></code>, <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/history.html#history-3" id="ref-for-history-3">History</a></code>, or <code class="idl"><a data-link-type="idl" href="https://www.w3.org/TR/WebCryptoAPI/#dfn-Crypto" id="ref-for-dfn-Crypto">Crypto</a></code>, are non-constructible because they are singletons representing access to per-window
information. In these cases, the Web IDL <a data-link-type="dfn" href="https://heycam.github.io/webidl/#dfn-namespace" id="ref-for-dfn-namespace">namespace</a> feature or some evolution of it might have
been a better fit, but they were designed before namespaces existed, and somewhat exceed the current
capabilities of namespaces. If you’re designing a new singleton, strongly consider using a <a data-link-type="dfn" href="https://heycam.github.io/webidl/#dfn-namespace" id="ref-for-dfn-namespace①">namespace</a> instead of a non-constructible class; if namespaces don’t yet have enough
capabilities, <a href="https://github.com/heycam/webidl/issues/new">file an issue on Web IDL</a> to
discuss.</p>
   <div class="note" role="note">
    <p>For any JavaScript developers still incredulous that it is possible to create an instance of
    a non-constructible class, we provide the following code example:</p>
<pre class="highlight"><c- kr>const</c-> secret <c- o>=</c-> <c- p>{};</c->

<c- kr>class</c-> NonConstructible <c- p>{</c->
    constructor<c- p>(</c->theSecret <c- o>=</c-> <c- kc>undefined</c-><c- p>)</c-> <c- p>{</c->
        <c- k>if</c-> <c- p>(</c->theSecret <c- o>!==</c-> secret<c- p>)</c-> <c- p>{</c->
            <c- k>throw</c-> <c- k>new</c-> TypeError<c- p>(</c-><c- u>"Illegal constructor."</c-><c- p>);</c->
        <c- p>}</c->

        <c- c1>// Set up the object.</c->
    <c- p>}</c->
<c- p>}</c->
</pre>
    <p>If the author of this code never exposes the <code>secret</code> variable to the outside world, they can
    reserve the ability to create instances of <code>NonConstructible</code> for themself: they can always do <code class="highlight"><c- kr>const</c-> instance <c- o>=</c-> <c- k>new</c-> NonConstructible<c- p>(</c->secret<c- p>)</c-></code>. But the outside world
    can never successfully "guess" the secret, and thus will always receive a <code class="idl"><a data-link-type="idl" href="https://heycam.github.io/webidl/#exceptiondef-typeerror" id="ref-for-exceptiondef-typeerror①">TypeError</a></code> when
    trying to construct an instance of <code>NonConstructible</code>.</p>
    <p>From this perspective, what browsers are doing when they create non-constructible classes
    isn’t magic: it’s just very tricky. The above section is aimed at urging browsers to avoid such
    tricks (or their equivalents in C++/Rust/etc.) whenever reasonable.</p>
   </div>
   <h3 class="heading settled" data-level="2.8" id="promises"><span class="secno">2.8. </span><span class="content">Design asynchronous APIs using Promises</span><a class="self-link" href="#promises"></a></h3>
   <p>Asynchronous APIs should generally be designed using promises
rather than callback functions.
This is the pattern that we’ve settled on for the Web platform,
and having APIs consistently use promises means that the APIs are
easier to use together (such as by chaining promises).
This pattern also tends to produce cleaner code than the use
of APIs with callback functions.</p>
   <p>Furthermore, you should carefully consider whether an API might need
to be asynchronous before making it a synchronous API.
An API might need to be asynchronous if:</p>
   <ul>
    <li data-md>
     <p>some implementations may (in at least some cases) wish to prompt the user
or ask the user for permission before allowing use of the API,</p>
    <li data-md>
     <p>implementations may need to consider information that might be stored
on disk in order to compute the result,</p>
    <li data-md>
     <p>implementations may need to interact with the network before returning
the result, or</p>
    <li data-md>
     <p>implementations may wish to do work on another thread or in another
process before returning the result.</p>
   </ul>
   <p>For more information on how to design APIs using promises,
and on when to use promises and when not to use promises,
see <strong><a href="https://www.w3.org/2001/tag/doc/promises-guide">Writing
Promise-Using Specifications</a></strong>.</p>
   <h3 class="heading settled" data-level="2.9" id="aborting"><span class="secno">2.9. </span><span class="content">Cancel asynchronous APIs/operations using AbortSignal</span><a class="self-link" href="#aborting"></a></h3>
   <p>Async functions that need cancellation should take an <code>AbortSignal</code> as part
of an options dictionary.</p>
   <p>Example:</p>
<pre class="language-js highlight"><c- kr>const</c-> controller <c- o>=</c-> <c- k>new</c-> AbortController<c- p>();</c->
<c- kr>const</c-> signal <c- o>=</c-> controller<c- p>.</c->signal<c- p>;</c->
geolocation<c- p>.</c->read<c- p>({</c-> signal <c- p>});</c->
</pre>
   <p>Reusing the same primitive everywhere has multiplicative effects throughout
the platform. In particular, there’s a common pattern of using a single <code>AbortSignal</code> for a bunch of ongoing operations, and then aborting them
(with the corresponding <code>AbortController</code>) when e.g. the user presses cancel,
or a single-page-app navigation occurs, or similar. So the minor extra
complexity for an individual API leads to a large reduction in complexity
when used with multiple APIs together.</p>
   <p>There might be cases where cancellation cannot be guaranteed. In these cases,
the <code>AbortController</code> can still be used because a call to <code>abort()</code> on <code>AbortController</code> is a request to abort. How you react to it depends on your spec.
Note, requestAbort() was considered in the AbortController design instead
of abort(), but the latter was chosen for brevity.</p>
   <h3 class="heading settled" data-level="2.10" id="secure-context"><span class="secno">2.10. </span><span class="content">Consider limiting new features to secure contexts</span><a class="self-link" href="#secure-context"></a></h3>
   <p>It may save you significant time and effort
to pre-emptively restrict your feature to Secure Contexts.</p>
   <p>The TAG is on the record in supporting
an industry-wide move to <a href="https://www.w3.org/2001/tag/doc/web-https">Secure the Web</a> and applaud <a href="https://blog.mozilla.org/security/2017/01/20/communicating-the-dangers-of-non-secure-http/">efforts</a> to shift web traffic to secure connections.
A great deal of effort has gone into debating
which features should be restricted to <a href="https://w3c.github.io/webappsec-secure-contexts/">Secure Contexts</a>.
Opinions vary amongst engine vendors, leading to difficult choices for feature designers.
Some vendors require <em>all</em> new features be restricted this way,
whereas others take a more selective approach.</p>
   <p>This backdrop makes it difficult to provide
advice about the extent to which your feature should be restricted.
What we <em>can</em> highlight is that Secure Context-restricted features
face the least friction in gaining wide adoption amongst these varying regimes.</p>
   <p>Specification authors can limit most features defined in <a href="https://heycam.github.io/webidl/">WebIDL</a>,
to secure contexts
by using the <code>[<a href="https://w3c.github.io/webappsec-secure-contexts/#integration-idl">SecureContext</a>]</code> extended attribute
on interfaces, namespaces, or their members (such as methods and attributes).
Similar ways of marking features as limited to secure contexts should be added
to other major points where the Web platform is extended over time
(for example, the definition of a new CSS property).
However, for some types of extension points (e.g., dispatching an event),
limitation to secure contexts should just
be defined in normative prose in the specification.</p>
   <p>As described in <a href="#feature-detect">§ 2.2 New features should be detectable</a>,
the existence of features should generally be detectable,
so that web content can act appropriately if the feature is present or not.
Since the detection should be the same no matter why the feature is unavailable,
a feature that is limited to secure contexts should, in non-secure contexts,
be indistinguishable from a feature that is not implemented.
However, if, for some reason
(a reason that itself requires serious justification),
it is not possible for developers to detect whether a feature is present,
limiting the feature to secure contexts
might cause problems
for libraries that may be used in either secure or non-secure contexts.</p>
   <p>If a feature would pose a risk to user privacy or security
without the authentication, integrity, or confidentiality
that is present only in secure contexts,
then the feature must be limited to secure contexts.
One example of a feature that should be limited to secure contexts
is geolocation, since the authentication and confidentiality provided by
secure contexts reduce the risks to user privacy.</p>
   <h3 class="heading settled" data-level="2.11" id="string-constants"><span class="secno">2.11. </span><span class="content">Constants, enums, and bitmasks</span><a class="self-link" href="#string-constants"></a></h3>
   <p>In many other platforms and programming languages, constants and enums are
commonly expressed using a integer constant, sometimes in conjunction with
a bitmask mechanism.</p>
   <p>However on the Web platform, it is more common to use a string constant for
the cases where a constant is needed. This is much more inspection friendly
for both development and expressing the constant codes through a user facing
interface, and in JavaScript engines, using integers offers no significant
performance benefit over strings.</p>
   <p>Strings do not directly address the use case for bitmasks. For these cases,
you should use an object dictionary which contains the state that the
bitmask is attempting to express, as object dictionaries can then be passed
around from method to method as needed as easily as the state in a single
bitmask value.</p>
   <h2 class="heading settled" data-level="3" id="event-design"><span class="secno">3. </span><span class="content">Event Design</span><a class="self-link" href="#event-design"></a></h2>
   <h3 class="heading settled" data-level="3.1" id="one-time-events"><span class="secno">3.1. </span><span class="content">Use promises for one time events</span><a class="self-link" href="#one-time-events"></a></h3>
   <p>Follow the <a href="https://www.w3.org/2001/tag/doc/promises-guide#one-time-events">advice</a> in the <strong><a href="https://www.w3.org/2001/tag/doc/promises-guide">Writing
Promise-Using Specifications</a></strong> guideline.</p>
   <h3 class="heading settled" data-level="3.2" id="promises-and-events"><span class="secno">3.2. </span><span class="content">Events should fire before Promises resolve</span><a class="self-link" href="#promises-and-events"></a></h3>
   <p>In the case that an asynchronous algorithm (Promise based) intends to dispatch
events, then such events should be dispatched before the Promise resolves, rather
than after.</p>
   <p>This ensures consistency, for instance if you have event handlers changing
state, you want all that state to be applied before acting on the resolved
promise, as you can subscribe to a promise at any time (before/after it has
resolved or rejected).</p>
   <h3 class="heading settled" data-level="3.3" id="dont-invent-event-like"><span class="secno">3.3. </span><span class="content">Don’t invent your own event listener-like infrastructure</span><a class="self-link" href="#dont-invent-event-like"></a></h3>
   <p>For recurring events, it could be convenient to create a custom pair of APIs to <code>"register"</code>/<code>"unregister"</code>, <code>"subscribe"</code>/<code>"unsubscribe"</code>, etc., that take a
callback and get invoked multiple times until paired cancel API is called.</p>
   <p>Instead, use the existing event registration pattern and separate API controls
to start/stop the underlying process (since event listeners should not have <a href="#events-are-for-notification">side-effects</a>).</p>
   <p>If the callback would have been provided specific data, then this data should
be added to an <code>Event</code> object (but see <a href="#state-and-subclassing">State
and <code>Event</code> subclasses</a> as this is not always necessary).</p>
   <p>In some cases, you can transfer the state that would be surfaced in callback
parameters into a more persistent object which, in turn, can inherit from <code>EventTarget</code>.</p>
   <p>In some cases you might not have an object to inherit from <code>EventTarget</code> but
it is usually possible to create such an object.</p>
   <p>For instance with Web Bluetooth you can add event listeners on a <code>Characteristic</code> object, which is obtained via <code>getCharacteristic()</code>. If you need to filter events,
it might be possible to create a filter like</p>
<pre class="language-js highlight"><c- kr>const</c-> filter <c- o>=</c-> navigator<c- p>.</c->nfc<c- p>.</c->createReadFilter<c- p>({</c->
  recordType<c- o>:</c-> <c- u>"json"</c->
<c- p>});</c->

<c- kr>const</c-> onMessage <c- o>=</c-> message <c- p>=></c-> <c- p>{</c-> … <c- p>};</c->
filter<c- p>.</c->addEventListener<c- p>(</c-><c- t>'exchange'</c-><c- p>,</c-> onMessage<c- p>);</c->
</pre>
   <h3 class="heading settled" data-level="3.4" id="always-add-event-handlers"><span class="secno">3.4. </span><span class="content">Always add event handler attributes</span><a class="self-link" href="#always-add-event-handlers"></a></h3>
   <p>For an object that inherits from <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget">EventTarget</a></code>, there are two techniques available for registering
an event handler (e.g., an event named "somethingchanged"):</p>
   <ol>
    <li data-md>
     <p><code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener" id="ref-for-dom-eventtarget-addeventlistener">addEventListener()</a></code> which allows authors to register for the event using the
event’s name (i.e., <code class="highlight">someobject<c- p>.</c->addEventListener<c- p>(</c-><c- u>"somethingchanged"</c-><c- p>,</c-> myhandler<c- p>)</c-></code>) and</p>
    <li data-md>
     <p><code>onsomethingchanged</code> IDL attributes which allow one event handler to be directly assigned to the
object (i.e., <code class="highlight">someobject<c- p>.</c->onsomethingchanged</code>).</p>
   </ol>
   <p>Because there are two techniques for registering events on objects inheriting from <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget①">EventTarget</a></code>,
authors may be tempted to omit the corresponding <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-idl-attributes" id="ref-for-event-handler-idl-attributes">event handler IDL attributes</a>. They may assume
that event handler IDL attributes are a legacy registration technique or are simply not needed
given that <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener" id="ref-for-dom-eventtarget-addeventlistener①">addEventListener()</a></code> is available as an alternative. However, it is
important to continue to define event handler IDL attributes because:</p>
   <ul>
    <li data-md>
     <p>they preserve consistency in the platform</p>
    <li data-md>
     <p>they enable feature-detection for the supported events (see <a href="#feature-detect">§ 2.2 New features should be detectable</a>)</p>
   </ul>
   <p>So, if the object inherits from <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget②">EventTarget</a></code>, add a corresponding <code>on<em>yourevent</em></code> <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-idl-attributes" id="ref-for-event-handler-idl-attributes①">event handler IDL attribute</a> to the interface.</p>
   <p class="note" role="note">Note that for HTML and SVG elements, it is traditional to add the <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-idl-attributes" id="ref-for-event-handler-idl-attributes②">event handler IDL attributes</a> on the <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers" id="ref-for-globaleventhandlers">GlobalEventHandlers</a></code> interface mixin, instead of
directly on the relevant element interface(s). Similarly, <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-idl-attributes" id="ref-for-event-handler-idl-attributes③">event handler IDL attributes</a> are traditionally added to <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/webappapis.html#windoweventhandlers" id="ref-for-windoweventhandlers">WindowEventHandlers</a></code> rather than <code class="idl"><a data-link-type="idl" href="https://html.spec.whatwg.org/multipage/window-object.html#window" id="ref-for-window①">Window</a></code>.</p>
   <h3 class="heading settled" data-level="3.5" id="events-are-for-notification"><span class="secno">3.5. </span><span class="content">Events are for notification</span><a class="self-link" href="#events-are-for-notification"></a></h3>
   <p>Try to design DOM events to deliver after-the-fact notifications of changes. It may be tempting to try to trigger side-effects from the action of <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent" id="ref-for-dom-eventtarget-dispatchevent">dispatchEvent()</a></code>, but in general this is <a href="https://lists.w3.org/Archives/Public/public-webapps/2014AprJun/0510.html">strongly discouraged</a> as it requires changes to the DOM specification when added. Your design will proceed more quickly if you avoid this pattern.</p>
   <h3 class="heading settled" data-level="3.6" id="favor-asynchronous-events"><span class="secno">3.6. </span><span class="content">Favor asynchronous events</span><a class="self-link" href="#favor-asynchronous-events"></a></h3>
   <p>A few events in the platform are specified to dispatch synchronously. These events cause problems for engines and performance issues in applications due to the possibility for re-entrant behavior they open up. The deprecated <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events">Mutation Events</a>, for instance, has caused many years of security issues. A more modern approach embodied in <a href="ihttps://developer.mozilla.org/en-US/docs/Web/API/MutationObserver">Mutation Observers</a> addresses most of the same use-cases in a higher-performance way which is easier to develop with and implement.</p>
   <p>If you feel you need a synchronous event in your design, please reconsider and ask the TAG for help in redesigning the API.</p>
   <h3 class="heading settled" data-level="3.7" id="state-and-subclassing"><span class="secno">3.7. </span><span class="content">State and <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#event" id="ref-for-event①">Event</a></code> subclasses</span><a class="self-link" href="#state-and-subclassing"></a></h3>
   <p>It’s tempting to create subclasses of <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#event" id="ref-for-event②">Event</a></code> for all event types. This is frequently unnecessary. Consider subclassing <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#event" id="ref-for-event③">Event</a></code> when adding unique methods and large amounts of state. In all other cases, using a "vanilla" event with state captured in the <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dom-event-target" id="ref-for-dom-event-target">target</a></code> object.</p>
   <h3 class="heading settled" data-level="3.8" id="events-vs-observers"><span class="secno">3.8. </span><span class="content">How to decide between Events and Observers</span><a class="self-link" href="#events-vs-observers"></a></h3>
   <p>Several recent additions to the platform employ an Observer pattern. <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#mutationobserver" id="ref-for-mutationobserver">MutationObserver</a></code>, <code class="idl"><a data-link-type="idl" href="#https://w3c.github.io/IntersectionObserver/" id="ref-for-https://w3c.github.io/IntersectionObserver/">IntersectionObserver</a></code>, <code class="idl"><a data-link-type="idl" href="#https://wicg.github.io/ResizeObserver/" id="ref-for-https://wicg.github.io/ResizeObserver/">ResizeObserver</a></code>, and <a href="https://github.com/WICG/indexed-db-observers">IndexedDB Observers</a> provide precedents for new Observer types.</p>
   <p>Many designs can be described as either Observers or <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget③">EventTarget</a></code>s. How to decide?</p>
   <p>In general, start your design process using an <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget④">EventTarget</a></code> and only move to Observers if and when events can’t be made to work well. Using an <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget⑤">EventTarget</a></code> ensures your feature benefits from improvements to the shared base class, such as the recent addition of the <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dom-addeventlisteneroptions-once" id="ref-for-dom-addeventlisteneroptions-once">once</a></code>.</p>
   <p>Observers have the following properties:</p>
   <ul>
    <li data-md>
     <p>Each instance is constructed with a callback, and optionally with some global options.</p>
    <li data-md>
     <p>Instances observe specific targets, using the <code>observe()</code> and <code>unobserve()</code> methods. The callback provided in the constructor is invoked when something interesting happens to those targets.</p>
    <li data-md>
     <p>Callbacks receive change records as arguments. These records contain the details about the interesting thing that happened. Multiple records can be delivered at once.</p>
    <li data-md>
     <p>Observation can be customized with additional options passed to <code>observe()</code>.</p>
    <li data-md>
     <p><code>disconnect()</code> stops observation.</p>
    <li data-md>
     <p><code>takeRecords()</code> synchronously returns records for all observed-but-not-yet-delivered occurrences.</p>
   </ul>
   <p class="example" id="example-7553a3ea"><a class="self-link" href="#example-7553a3ea"></a> <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#mutationobserver" id="ref-for-mutationobserver①">MutationObserver</a></code> takes a callback which receives <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#mutationrecord" id="ref-for-mutationrecord">MutationRecord</a></code>s. It cannot be customized at construction time, but each observation can be customized using the <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dictdef-mutationobserverinit" id="ref-for-dictdef-mutationobserverinit">MutationObserverInit</a></code> set of options. It observes <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#node" id="ref-for-node">Node</a></code>s as targets. </p>
   <p class="example" id="example-4a2bf527"><a class="self-link" href="#example-4a2bf527"></a> <code class="idl"><a data-link-type="idl" href="#https://w3c.github.io/IntersectionObserver/" id="ref-for-https://w3c.github.io/IntersectionObserver/①">IntersectionObserver</a></code> takes a callback which receives <code class="idl"><a data-link-type="idl" href="#https://w3c.github.io/IntersectionObserver/" id="ref-for-https://w3c.github.io/IntersectionObserver/②">IntersectionObserverEntry</a></code>s. It can be customized at construction time using the <code class="idl"><a data-link-type="idl" href="#https://w3c.github.io/IntersectionObserver/" id="ref-for-https://w3c.github.io/IntersectionObserver/③">IntersectionObserverInit</a></code> set of options, but each observation is not further customizable. It observers <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#element" id="ref-for-element">Element</a></code>s as targets. </p>
   <p>Observers involve defining a new class, dictionaries for options, and a new type for the delivered records. For the cost, you gain a few advantages:</p>
   <ul>
    <li data-md>
     <p>Instances can be customized at observation time. The <code>observe()</code> method of an <code>Observer</code> can take options, allowing per-callback customization. This is not possible with <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener" id="ref-for-dom-eventtarget-addeventlistener②">addEventListener()</a></code>.</p>
    <li data-md>
     <p>Reuse of their creation-time customizations on multiple targets.</p>
    <li data-md>
     <p>Easy disconnection from multiple targets via <code>disconnect()</code>.</p>
    <li data-md>
     <p>Built-in support for synchronously probing system state. Both <code>Observer</code>s and <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget⑥">EventTarget</a></code>s can batch occurrences and deliver them later, but <code>Observer</code>s have a <code>takeRecords()</code> method which allows synchronously probing waiting until the next batched delivery.</p>
    <li data-md>
     <p>Because they are single-purpose, you don’t need to specify an event type.</p>
   </ul>
   <p><code>Observer</code>s and <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget⑦">EventTarget</a></code>s overlap in the following ways:</p>
   <ul>
    <li data-md>
     <p>Both can be customized at creation time.</p>
    <li data-md>
     <p>Both can batch occurrences and deliver them at any time. <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget⑧">EventTarget</a></code>s don’t need to be synchronous; they can use microtask timing, idle timing, animation-frame timing, etc. You don’t need an <code>Observer</code> to get special timing or batching.</p>
    <li data-md>
     <p>Neither <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget⑨">EventTarget</a></code>s nor <code>Observer</code>s need participate in a DOM tree (bubbling/capture and cancellation). Most prominent <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget①⓪">EventTarget</a></code>s are <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#node" id="ref-for-node①">Node</a></code>s in the DOM tree, but many other events are standalone; e.g. <code class="idl"><a data-link-type="idl" href="https://w3c.github.io/IndexedDB/#idbdatabase" id="ref-for-idbdatabase">IDBDatabase</a></code> and <code class="idl"><a data-link-type="idl" href="https://xhr.spec.whatwg.org/#xmlhttprequesteventtarget" id="ref-for-xmlhttprequesteventtarget">XMLHttpRequestEventTarget</a></code>. Even when using <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#node" id="ref-for-node②">Node</a></code>s, you can leave your events can be designed to be non-bubbling and non-cancelable to get that <code>Observer</code>-esque feel.</p>
   </ul>
   <div class="example" id="example-5ebfa3a4">
    <a class="self-link" href="#example-5ebfa3a4"></a> Here is an example of using a hypothetical version of <code class="idl"><a data-link-type="idl" href="#https://w3c.github.io/IntersectionObserver/" id="ref-for-https://w3c.github.io/IntersectionObserver/④">IntersectionObserver</a></code> that is an <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#eventtarget" id="ref-for-eventtarget①①">EventTarget</a></code> subclass: 
<pre class="highlight"><c- kr>const</c-> io <c- o>=</c-> <c- k>new</c-> ETIntersectionObserver<c- p>(</c->element<c- p>,</c-> <c- p>{</c-> root<c- p>,</c-> rootMargin<c- p>,</c-> threshold <c- p>});</c->

<c- a>function</c-> listener<c- p>(</c->e<c- p>)</c-> <c- p>{</c->
    <c- k>for</c-> <c- p>(</c-><c- kr>const</c-> change <c- k>of</c-> e<c- p>.</c->changes<c- p>)</c-> <c- p>{</c->
        <c- c1>// ...</c->
    <c- p>}</c->
<c- p>}</c->

io<c- p>.</c->addEventListener<c- p>(</c-><c- u>"intersect"</c-><c- p>,</c-> listener<c- p>);</c->
io<c- p>.</c->removeEventListener<c- p>(</c-><c- u>"intersect"</c-><c- p>,</c-> listener<c- p>);</c->
</pre>
    <p>As you can see, we’ve lost some functionality compared to the <code>Observer</code> version: the ability to easily observe multiple elements with the same options, or the <code>takeRecords()</code> and <code>disconnect()</code> methods. We’re also forced to add the rather-redundant <code>"intersect"</code> event type to our subscription calls.</p>
    <p>However, we haven’t lost the batching, timing, or creation-time customization, and the <code>ETIntersectionObserver</code> doesn’t participate in a hierarchy. These aspects can be achieved with either design.</p>
   </div>
   <h2 class="heading settled" data-level="4" id="types-and-units"><span class="secno">4. </span><span class="content">Types and Units</span><a class="self-link" href="#types-and-units"></a></h2>
   <h3 class="heading settled" data-level="4.1" id="numeric-types"><span class="secno">4.1. </span><span class="content">Use numeric types appropriately</span><a class="self-link" href="#numeric-types"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-webidl">[WEBIDL]</a> contains many numeric types. However, it is very
rare that its more specific ones are actually appropriate.</p>
   <p>JavaScript has only one numeric type, Number: IEEE 754 double-precision
floating point, including ±0, ±Infinity, and NaN (although thankfully only one). The Web IDL "types" are coercion rules that apply when accepting an argument or triggering a setter. For example, a Web IDL <code>unsigned short</code> roughly says: "when someone passes this as an argument, take it modulo 65536 before doing any further processing". That is very rarely a useful thing to do.</p>
   <p>Instead, you will want to stick with one of:</p>
   <dl>
    <dt data-md><code>unrestricted double</code>
    <dd data-md>
     <p>When truly any JavaScript number will do, including infinities and NaN</p>
    <dt data-md><code>double</code>
    <dd data-md>
     <p>Any JavaScript number excluding infinities and NaN</p>
    <dt data-md><code>[EnforceRange] long long</code>
    <dd data-md>
     <p>Any JavaScript number in the integer-representable range, throwing a <code class="highlight">TypeError</code> outside the range and rounding inside of it</p>
    <dt data-md><code>[EnforceRange] unsigned long long</code>
    <dd data-md>
     <p>Any nonnegative JavaScript number in the integer-representable range, throwing a <code class="highlight">TypeError</code> outside the range and rounding inside of it</p>
    <dt data-md><code>bigint</code>
    <dd data-md>
     <p>When the possible integer values range more broadly than JavaScript numbers can accurately represent</p>
   </dl>
   <p>Additionally, you can combine any of the above with an extra line in your
algorithm to validate that the number is within the expected domain-specific
range, and throwing or performing other actions in response. (While it is very
rarely appropriate to modify author input by taking it modulo 65536, it might be
appropriate to take it modulo 360, for example.)</p>
   <p>A special case of domain-specific validation, which Web IDL already has you
covered for, is the 0–255 range. This can be written as <code>[EnforceRange]
octet</code>: any JavaScript number in the range 0–255, throwing a <code class="highlight">TypeError</code> outside the range and rounding inside of it.
(And indeed, if it turns out that the other power-of-two ranges are semantically
meaningful for your domain, such that you want the modulo or range-checking
behavior, feel free to use them.)</p>
   <div class="note" role="note"> Those coming from other languages should carefully note that despite their
names, <code>long long</code> and <code>unsigned long long</code> only have 53
bits of precision, and not 64. </div>
   <p><code>bigint</code> is recommended to be used <em>only</em> in circumstances
where a <code>[EnforceRange] long long</code> or <code>[EnforceRange] unsigned
long long</code> would not work in terms of expressivity: that is, only when
values greater than 2<sup>53</sup> or less than -2<sup>53</sup> are expected. In
particular, APIs should not use the <code>bigint</code> type simply because the
input is an integer—<code>bigint</code> is for big integers (hence the
name!).</p>
   <p>Transparent support for inputs being either JavaScript Number of BigInt types is
discouraged, unless there is a domain-specific requirement to support it. As far
as ergonomics, JavaScript developers are expected to keep track of whether their
values are Numbers or BigInts. Sloppiness or implicit conversions here could
lead to a loss of precision, defeating the purpose of using BigInt.</p>
   <p>Further, try to resist doubling up the surface area of an API in order to
provide both <code>BigInt</code> and <code>Number</code> variants of an API. As an API designer,
consider it your job to chose the correct numeric type for the feature being
exposed.</p>
   <h3 class="heading settled" data-level="4.2" id="milliseconds"><span class="secno">4.2. </span><span class="content">Use milliseconds for time measurement</span><a class="self-link" href="#milliseconds"></a></h3>
   <p>Any web API that accepts a time measurement should do so in milliseconds. This
is a tradition stemming from <code class="highlight">setTimeout</code> and the <code class="highlight">Date</code> API, and carried through since then.</p>
   <p>Even if seconds (or some other unit) are more natural in the domain of an API, sticking with
milliseconds ensures interoperability with the rest of the platform, allowing easy arithmetic with
other time quantities.</p>
   <p>Note that high-resolution time is usually represented as fractional milliseconds, not e.g. as
nanoseconds.</p>
   <h3 class="heading settled" data-level="4.3" id="times-and-dates"><span class="secno">4.3. </span><span class="content">Use the appropriate type to represent times and dates</span><a class="self-link" href="#times-and-dates"></a></h3>
   <p>When representing date-times on the platform, use the <code class="idl"><a data-link-type="idl" href="https://heycam.github.io/webidl/#DOMTimeStamp" id="ref-for-DOMTimeStamp">DOMTimeStamp</a></code> type, with values being the
 number of milliseconds relative to 1970-01-01T00:00:00Z.</p>
   <p>The JavaScript <code class="highlight">Date</code> class must not be used for this purpose. <code class="highlight">Date</code> objects
are mutable (and there is no way to make them immutable), which comes with a host of attendant
problems.</p>
   <div class="note" role="note">
     For more background on why <code class="highlight">Date</code> must not be used, see the following: 
    <ul>
     <li data-md>
      <p><a href="https://esdiscuss.org/topic/frozen-date-objects">Frozen date objects?</a> on
es-discuss</p>
     <li data-md>
      <p><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=22824">Remove Date from Web IDL</a> on the Web IDL Bugzilla</p>
    </ul>
   </div>
   <p>While in theory time is monotonically increasing,
values like <code class="idl"><a data-link-type="idl" href="https://heycam.github.io/webidl/#DOMTimeStamp" id="ref-for-DOMTimeStamp①">DOMTimeStamp</a></code> that represent time since 1970 are derived from the system’s clock,
which may sometimes move backwards
(for example, from NTP or manual adjustment),
causing the timestamp values to decrease over time.
They may also remain the same due to the limitation of millisecond resolution.
Thus, for time stamps that do not need to correspond to an absolute time,
consider using <code class="idl"><a data-link-type="idl" href="https://w3c.github.io/hr-time/#dom-domhighrestimestamp" id="ref-for-dom-domhighrestimestamp">DOMHighResTimeStamp</a></code>,
which provides monotonically non-decreasing sub-millisecond timestamps
that are comparable within a single <a data-link-type="dfn" href="https://html.spec.whatwg.org/multipage/browsers.html#browsing-context" id="ref-for-browsing-context">browsing context</a> or web worker.
See <a data-link-type="biblio" href="#biblio-highres-time">[HIGHRES-TIME]</a> for more details.</p>
   <h3 class="heading settled" data-level="4.4" id="error-types"><span class="secno">4.4. </span><span class="content">Use Error or DOMException for errors</span><a class="self-link" href="#error-types"></a></h3>
   <p>Errors in web APIs should be represented as <a data-link-type="dfn" href="https://tc39.github.io/ecma262/#sec-error-objects" id="ref-for-sec-error-objects">ECMAScript error objects</a> (perhaps via the WebIDL <code class="idl"><a data-link-type="idl">Error</a></code> type)
or as <code class="idl"><a data-link-type="idl" href="https://heycam.github.io/webidl/#idl-DOMException" id="ref-for-idl-DOMException">DOMException</a></code>.
There was at one point a trend to use <code class="idl"><a data-link-type="idl" href="https://dom.spec.whatwg.org/#domerror" id="ref-for-domerror">DOMError</a></code> when
objects had a property representing an error.
However, we no longer believe there was value in this split,
and therefore suggest that ECMAScript error objects (e.g., <code class="idl"><a data-link-type="idl" href="https://heycam.github.io/webidl/#exceptiondef-typeerror" id="ref-for-exceptiondef-typeerror②">TypeError</a></code>)
or <code class="idl"><a data-link-type="idl" href="https://heycam.github.io/webidl/#idl-DOMException" id="ref-for-idl-DOMException①">DOMException</a></code> should be used for errors,
whether they are exceptions, promise rejection values, or properties.</p>
   <h2 class="heading settled" data-level="5" id="device-apis"><span class="secno">5. </span><span class="content">OS and Device Wrapper APIs</span><a class="self-link" href="#device-apis"></a></h2>
   <p>It is increasingly common to see new APIs developed in the web platform for interacting with
devices. For example, authors wish to be able to use the web to connect with their <a href="https://www.w3.org/TR/mediacapture-streams/">microphones and cameras</a>, <a href="https://www.w3.org/TR/generic-sensor/">generic sensors</a> (such as gyroscope and
accelerometer), <a href="https://www.w3.org/community/web-bluetooth/">Bluetooth</a> and <a href="https://wicg.github.io/webusb/">USB</a>-connected peripherals, <a href="https://www.w3.org/community/autowebplatform/">automobiles</a>, toothbrush, etc. This
section contains principles for consideration when designing APIs for devices.</p>
   <p>These can be functionality provided by the underlying operating system, or provided by a native
third-party library to interact with a device. These are an abstraction which "wrap" the
native functionality without introducing significant complexity while securing the API surface
to the browser, hence are called wrapper APIs.</p>
   <h3 class="heading settled" data-level="5.1" id="device-ids"><span class="secno">5.1. </span><span class="content">Use care when exposing device identifiers</span><a class="self-link" href="#device-ids"></a></h3>
   <p>Exposing device identifiers increases the fingerprinting surface of a user
agent conversely reducing the user’s privacy. Think carefully about whether it is really necessary
to expose the unique identifier at all. Please read the TAG’s finding on <a href="http://www.w3.org/2001/tag/doc/unsanctioned-tracking/">unsanctioned tracking</a> for
additional details. Despite this general concern, it may be very useful or necessary to expose a
device’s unique identifier to the web platform. The following guidelines will help ensure that this
is done in a consistent and privacy-friendly way:</p>
   <dl>
    <dt data-md>Limit identifiable information in the id
    <dd data-md>
     <p>As much as possible, device ids exposed to the web platform should not contain identifiable
 information such as branding, make and model numbers, etc. In many cases using a randomized
 number or unique id is preferable to a generic string identifier such as "device1".</p>
    <dd data-md>
     <p>Device ids expressed as numbers should contain sufficient entropy so as to avoid re-use or
 potential sharing among other devices, and should not be easily guessable.</p>
    <dt data-md>Keep the user in control
    <dd data-md>
     <p>Any existing device ids mapped to or stored with the current session by the user agent should
 be cleared when users elect to "clear their cookies" (and other related settings). Above all,
 the user should be in control of this potential tracking state and be able to reset it on
 demand.</p>
    <dt data-md>Hide sensitive ids behind a user permission
    <dd data-md>
     <p>Where device identification does not make sense to be expressed in an anonymous way, access to
 the identifier should be limited by default. One way to limit exposure is to only surface the
 identifier to author code <em>after</em> obtaining permission from the user.</p>
    <dt data-md>Tie ids to the same-origin model
    <dd data-md>
     <p>Identifiers should be unique to the origin of the web content that is attempting to access
 them. Web content from one origin should receive an identifier that is distinct from the
 identifier given to web content from any other origin despite the physical device being the
 same.</p>
    <dd data-md>
     <p>Within an origin, ids may have a stable representation to web content. This ensures a
 consistent developer experience if requesting the same device twice.</p>
    <dt data-md>Persistable when necessary
    <dd data-md>
     <p>Device identifiers obtained after a complex or time-consuming device selection process may
 prefer that author code be allowed to persist the id for use in a later session in order to
 avoid the selection process a second time. In this case, the API should not only provide a
 stable id during the session for the given origin, but also be able to deterministically produce
 the same id in subsequent sessions.</p>
   </dl>
   <h3 class="heading settled" data-level="5.2" id="wrapper-apis"><span class="secno">5.2. </span><span class="content">Native APIs don’t typically translate well to the web</span><a class="self-link" href="#wrapper-apis"></a></h3>
   <p>Many modern operating systems come with convenience APIs, which abstract away
normally complex technology in the form of higher level user-friendly APIs.</p>
   <p>Exposing these APIs to the web platform is getting more and more common, but you
need to be careful when exposing these to the web platform.</p>
   <dl>
    <dt data-md>Generalize interface when underlying API is overly specific
    <dd data-md>
     <p>Don’t blindly map native convenience APIs 1:1 to the web platform.
Native APIs do not translate well to the web platform, and doing so may result
in a API shape which is difficult to implement across a variety of underlying
platforms and native libraries.</p>
     <p>Especially be careful about exposing the exact lifecycle and data
structures of the underlying native APIs. Think about making an API that <a href="#string-constants">fits well in with existing web platform APIs</a> and which can be expressed in
commonly available low-level APIs.</p>
    <dt data-md>Prefer asynchronous function by returning promises
    <dd data-md>
     <p>Even if the underlying API is synchronous, this does not necessarily mean it
translates well when ported to the web platform. Exposing a synchronous native
API to the web platform is generally discouraged, and should be
provided as a promise based API whenever possible.</p>
     <p>Doing this also allows putting the API behind a permission if it is
necessary, especially if the API depends on I/O or in the future may need to
be isolated to a separate process.</p>
    <dt data-md>Don’t overconstrain or overfit the API to the underlying (wrapped) OS
    <dd data-md>
     <p>When designing a wrapper API, you should consider how different implementations
(operating systems and platforms) provide this functionality. Ideally the entire
specification is implementable across platforms, but in some cases it may be
desirable to expose distinctions made on only some platforms.</p>
     <p>These distinctions should be clearly noted if they are known in advance.</p>
    <dt data-md>Do not propose black-box proprietary library or dedicated hardware processor dependencies
    <dd data-md>
     <p>Black-box dependencies are strongly discouraged, as this not only prevents wide
implementor adoption, but is unhealthy to the open nature of the web.</p>
    <dt data-md>Underlying protocols should be open
    <dd data-md>
     <p>APIs which require exchange with external hardware or services should not depend
on closed protocols.</p>
    <dt data-md>Be offline friendly
    <dd data-md>
     <p>Web platform APIs should ideally not have a hard dependency on online services.
The availability of these services across different regions may vary, users
may be offline, and the online services have no guarantee of being always
available.</p>
    <dt data-md>Avoid additional fingerprinting surfaces
    <dd data-md>
     <p>Wrapper APIs can expose unintentionally expose the user to a wider fingerprinting surface.
Please read the TAG’s finding on <a href="http://www.w3.org/2001/tag/doc/unsanctioned-tracking/">unsanctioned tracking</a> for additional details.</p>
   </dl>
   <h2 class="heading settled" data-level="6" id="other-considerations"><span class="secno">6. </span><span class="content">Other API Design Considerations</span><a class="self-link" href="#other-considerations"></a></h2>
   <h3 class="heading settled" data-level="6.1" id="design-resources"><span class="secno">6.1. </span><span class="content">Privacy, Security, Accessibility, and Internationalization</span><a class="self-link" href="#design-resources"></a></h3>
   <p>It is important not to neglect other aspects of API design such as privacy, security, accessibility, and internationalization.
Please take advantage of these other excellent resources in your design process:</p>
   <ul>
    <li data-md>
     <p><a href="https://w3c.github.io/privacy-considerations/">Privacy Considerations for Web Protocols</a></p>
    <li data-md>
     <p><a href="https://www.w3.org/TR/security-privacy-questionnaire/">Self-Review Questionnaire: Security and Privacy</a></p>
    <li data-md>
     <p><a href="https://w3c.github.io/apa/fast/">Web Technology Accessibility Guidelines</a></p>
    <li data-md>
     <p><a href="https://w3c.github.io/bp-i18n-specdev/">Internationalization Best Practices for Spec Developers</a></p>
   </ul>
   <h3 class="heading settled" data-level="6.2" id="polyfills"><span class="secno">6.2. </span><span class="content">Polyfills</span><a class="self-link" href="#polyfills"></a></h3>
   <p>Polyfills can be hugely beneficial in helping to roll out new features to the web platform. The
Technical Architecture Group <a href="https://www.w3.org/2001/tag/doc/polyfills/">finding on Polyfills and the Evolution of the Web</a> offers guidance
that should be considered in the development of new features, notably:</p>
   <ul>
    <li data-md>
     <p>Being "polyfillable" is not essential but <strong>is</strong> beneficial</p>
    <li data-md>
     <p><a href="#feature-detect">§ 2.2 New features should be detectable</a></p>
    <li data-md>
     <p>Polyfill development should be encouraged</p>
   </ul>
   <h2 class="heading settled" data-level="7" id="spec-writing"><span class="secno">7. </span><span class="content">Writing good specifications</span><a class="self-link" href="#spec-writing"></a></h2>
   <p>This document mostly covers API design for the Web,
but those who design APIs are hopefully also writing specifications
for the APIs that they design.</p>
   <h3 class="heading settled" data-level="7.1" id="writing-resources"><span class="secno">7.1. </span><span class="content">Other resources</span><a class="self-link" href="#writing-resources"></a></h3>
   <p>Some useful advice on how to write specifications is available elsewhere:</p>
   <ul>
    <li data-md>
     <p><a href="https://ln.hixie.ch/?start=1140242962&amp;count=1">Writing
specifications: Kinds of statements</a> (Ian Hickson, 2006)</p>
    <li data-md>
     <p><a href="https://www.w3.org/TR/qaframe-spec/">QA Framework:
Specification Guidelines</a> (W3C QA Working Group, 2005)</p>
   </ul>
   <h3 class="heading settled" data-level="7.2" id="algorithms"><span class="secno">7.2. </span><span class="content">Specify clearly enough so that algorithms are unambiguous</span><a class="self-link" href="#algorithms"></a></h3>
   <p>Specification text is often more precise
when it is written using an explicit sequence of steps.
Using an ordered sequence of steps makes it clear how the required behaviors interact.
For example, if there are multiple error conditions present,
a specification that describes the behavior using a sequence of steps
will make it clear which error will be reported,
since the different errors would be checked and reported in different steps.</p>
   <p>Likewise, describing state using explicit flags also makes behavior clearer.
Using explicit flags makes it clear
whether or not the state changes in different error conditions,
and makes it clear when the state described by the flags is reset.</p>
   <p>Whenever these differences could be observable to web content
and there isn’t a good reason to allow variation between implementations,
it is important that they be specified unambiguously,
so that implementations interoperate
and web content doesn’t end up
depending on the behavior of one implementation and failing in another
(which can cause higher development costs to fix the content for all browsers,
or costs to users of broken content if it wasn’t detected).</p>
   <p>However, sequences of steps are not the only way of making the specification precise enough.
When there are particular characteristics
that specification editors want to ensure the specification always satisfies,
it may be better to use a less algorithmic way of formal specification
that ensures these characteristics are always true.
Developing these other ways of specifying behavior formally
is more important when the algorithms would be more repetitive.
These formal specification techniques can include dependencies on
languages such as <a data-link-type="biblio" href="#biblio-webidl">[WEBIDL]</a>, on grammar productions,
or the development of new languages for defining pieces of the specification.
Merely having a formal syntax is not sufficient, though;
the requirements that the formal definitions place on implementations must still be clearly defined,
which generally requires specifying some algorithms (or, sometimes, another layer of formal syntax) that define what the formal syntax means,
and then using the more-readable formal syntax to avoid
excessive repetition of the less-readable algorithms.
There are also possibilities in-between, for example,
if it is desirable to ensure that an algorithm can be implemented with a state machine,
it may be preferable to specify it in an algorithmic way that incorporates explicit states
so that the specification authors avoid accidentally creating more states than intended.</p>
   <p>When specifying in an algorithmic way,
it is generally good to match the algorithms that implementations would use,
even if this is somewhat less convenient for specification authors,
as long as doing so would not significantly increase the specification’s complexity.
For example, it is better to specify CSS selector matching
by moving right to left across <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#selector-combinator" id="ref-for-selector-combinator">combinators</a>,
since that is what implementations do.
This avoids the risk of future problems caused by new features
that would be slightly different (in unimportant ways)
between implementations based on one algorithm and implementations based on a different one.
Thus, it avoids small future divergence in behavior between specification and implementations.
It also helps to keep the costs of specifying features aligned with implementing them,
since the complexity of adding a feature to the specification is more likely to be related
to the cost of adding it to implementations.</p>
   <p>Algorithms in specifications should also reflect best practices in programming.
For example, they should explicitly describe the inputs and outputs of the algorithm,
rather than relying on "stack introspection" or handwaving.
They should also avoid side-effects when possible.</p>
   <p>The Infra Standard offers <a href="https://infra.spec.whatwg.org/#algorithms">some useful definitions
and terminology</a> for defining algorithms.</p>
   <p>Specifications that define things using step-by-step algorithms should still be readable.
Partly, this is through good practices that also apply to writing code,
such as avoiding unneeded extra steps, and by using good naming.
However, it’s often useful to explain the purpose of the algorithm in prose
(e.g., "take the following steps, which ensure that there is at most one pending X
callback per toplevel browsing context")
so that readers can quickly decide whether they need to read the steps in detail.</p>
  </main>
  <div data-fill-with="conformance">
   <h2 class="no-ref no-num heading settled" id="conformance"><span class="content"> Conformance</span><a class="self-link" href="#conformance"></a></h2>
   <p> Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology.
            The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL”
            in the normative parts of this document
            are to be interpreted as described in RFC 2119.
            However, for readability,
            these words do not appear in all uppercase letters in this specification. </p>
   <p> All of the text of this specification is normative
            except sections explicitly marked as non-normative, examples, and notes. <a data-link-type="biblio" href="#biblio-rfc2119">[RFC2119]</a> </p>
   <p> Examples in this specification are introduced with the words “for example”
            or are set apart from the normative text with <code>class="example"</code>, like this: </p>
   <div class="example" id="example-example"><a class="self-link" href="#example-example"></a> This is an example of an informative example. </div>
   <p> Informative notes begin with the word “Note”
            and are set apart from the normative text with <code>class="note"</code>, like this: </p>
   <p class="note" role="note"> Note, this is an informative note. </p>
  </div>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>
  <h2 class="no-num no-ref heading settled" id="index"><span class="content">Index</span><a class="self-link" href="#index"></a></h2>
  <h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="content">Terms defined by this specification</span><a class="self-link" href="#index-defined-here"></a></h3>
  <ul class="index">
   <li><a href="#live-object">live object</a><span>, in §2.4</span>
   <li><a href="#static-object">static object</a><span>, in §2.4</span>
  </ul>
  <aside class="dfn-panel" data-for="term-for-at-ruledef-supports">
   <a href="https://drafts.csswg.org/css-conditional-3/#at-ruledef-supports">https://drafts.csswg.org/css-conditional-3/#at-ruledef-supports</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-at-ruledef-supports">2.2. New features should be detectable</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-window-getcomputedstyle">
   <a href="https://drafts.csswg.org/cssom-1/#dom-window-getcomputedstyle">https://drafts.csswg.org/cssom-1/#dom-window-getcomputedstyle</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-window-getcomputedstyle">2.4. Consider whether objects should be live or static</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-domerror">
   <a href="https://dom.spec.whatwg.org/#domerror">https://dom.spec.whatwg.org/#domerror</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-domerror">4.4. Use Error or DOMException for errors</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-domtokenlist">
   <a href="https://dom.spec.whatwg.org/#domtokenlist">https://dom.spec.whatwg.org/#domtokenlist</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-domtokenlist">2.7. Classes should have constructors when possible</a> <a href="#ref-for-domtokenlist①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-element">
   <a href="https://dom.spec.whatwg.org/#element">https://dom.spec.whatwg.org/#element</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-element">3.8. How to decide between Events and Observers</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-event">
   <a href="https://dom.spec.whatwg.org/#event">https://dom.spec.whatwg.org/#event</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-event">2.7. Classes should have constructors when possible</a>
    <li><a href="#ref-for-event①">3.7. State and Event subclasses</a> <a href="#ref-for-event②">(2)</a> <a href="#ref-for-event③">(3)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-eventtarget">
   <a href="https://dom.spec.whatwg.org/#eventtarget">https://dom.spec.whatwg.org/#eventtarget</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-eventtarget">3.4. Always add event handler attributes</a> <a href="#ref-for-eventtarget①">(2)</a> <a href="#ref-for-eventtarget②">(3)</a>
    <li><a href="#ref-for-eventtarget③">3.8. How to decide between Events and Observers</a> <a href="#ref-for-eventtarget④">(2)</a> <a href="#ref-for-eventtarget⑤">(3)</a> <a href="#ref-for-eventtarget⑥">(4)</a> <a href="#ref-for-eventtarget⑦">(5)</a> <a href="#ref-for-eventtarget⑧">(6)</a> <a href="#ref-for-eventtarget⑨">(7)</a> <a href="#ref-for-eventtarget①⓪">(8)</a> <a href="#ref-for-eventtarget①①">(9)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-htmlcollection">
   <a href="https://dom.spec.whatwg.org/#htmlcollection">https://dom.spec.whatwg.org/#htmlcollection</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-htmlcollection">1.3. Do not expose garbage collection</a> <a href="#ref-for-htmlcollection①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-mutationobserver">
   <a href="https://dom.spec.whatwg.org/#mutationobserver">https://dom.spec.whatwg.org/#mutationobserver</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-mutationobserver">3.8. How to decide between Events and Observers</a> <a href="#ref-for-mutationobserver①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dictdef-mutationobserverinit">
   <a href="https://dom.spec.whatwg.org/#dictdef-mutationobserverinit">https://dom.spec.whatwg.org/#dictdef-mutationobserverinit</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dictdef-mutationobserverinit">3.8. How to decide between Events and Observers</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-mutationrecord">
   <a href="https://dom.spec.whatwg.org/#mutationrecord">https://dom.spec.whatwg.org/#mutationrecord</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-mutationrecord">3.8. How to decide between Events and Observers</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-node">
   <a href="https://dom.spec.whatwg.org/#node">https://dom.spec.whatwg.org/#node</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-node">3.8. How to decide between Events and Observers</a> <a href="#ref-for-node①">(2)</a> <a href="#ref-for-node②">(3)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-nodelist">
   <a href="https://dom.spec.whatwg.org/#nodelist">https://dom.spec.whatwg.org/#nodelist</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-nodelist">2.4. Consider whether objects should be live or static</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-eventtarget-addeventlistener">
   <a href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener">https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-eventtarget-addeventlistener">3.4. Always add event handler attributes</a> <a href="#ref-for-dom-eventtarget-addeventlistener①">(2)</a>
    <li><a href="#ref-for-dom-eventtarget-addeventlistener②">3.8. How to decide between Events and Observers</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-eventtarget-dispatchevent">
   <a href="https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent">https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-eventtarget-dispatchevent">3.5. Events are for notification</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-document-getelementsbytagname">
   <a href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname">https://dom.spec.whatwg.org/#dom-document-getelementsbytagname</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-document-getelementsbytagname">2.4. Consider whether objects should be live or static</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-addeventlisteneroptions-once">
   <a href="https://dom.spec.whatwg.org/#dom-addeventlisteneroptions-once">https://dom.spec.whatwg.org/#dom-addeventlisteneroptions-once</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-addeventlisteneroptions-once">3.8. How to decide between Events and Observers</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-parentnode-queryselectorall">
   <a href="https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall">https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-parentnode-queryselectorall">2.4. Consider whether objects should be live or static</a> <a href="#ref-for-dom-parentnode-queryselectorall①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-event-target">
   <a href="https://dom.spec.whatwg.org/#dom-event-target">https://dom.spec.whatwg.org/#dom-event-target</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-event-target">3.7. State and Event subclasses</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-domhighrestimestamp">
   <a href="https://w3c.github.io/hr-time/#dom-domhighrestimestamp">https://w3c.github.io/hr-time/#dom-domhighrestimestamp</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-domhighrestimestamp">4.3. Use the appropriate type to represent times and dates</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-globaleventhandlers">
   <a href="https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers">https://html.spec.whatwg.org/multipage/webappapis.html#globaleventhandlers</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-globaleventhandlers">3.4. Always add event handler attributes</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-htmlconstructor">
   <a href="https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor">https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-htmlconstructor">2.7. Classes should have constructors when possible</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-htmlhtmlelement">
   <a href="https://html.spec.whatwg.org/multipage/semantics.html#htmlhtmlelement">https://html.spec.whatwg.org/multipage/semantics.html#htmlhtmlelement</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-htmlhtmlelement">2.5. Use casing rules consistent with existing APIs</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-htmlimageelement">
   <a href="https://html.spec.whatwg.org/multipage/embedded-content.html#htmlimageelement">https://html.spec.whatwg.org/multipage/embedded-content.html#htmlimageelement</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-htmlimageelement">2.5. Use casing rules consistent with existing APIs</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-history-3">
   <a href="https://html.spec.whatwg.org/multipage/history.html#history-3">https://html.spec.whatwg.org/multipage/history.html#history-3</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-history-3">2.7. Classes should have constructors when possible</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-imagebitmap">
   <a href="https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#imagebitmap">https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#imagebitmap</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-imagebitmap">2.7. Classes should have constructors when possible</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-navigator">
   <a href="https://html.spec.whatwg.org/multipage/system-state.html#navigator">https://html.spec.whatwg.org/multipage/system-state.html#navigator</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-navigator">2.7. Classes should have constructors when possible</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-window">
   <a href="https://html.spec.whatwg.org/multipage/window-object.html#window">https://html.spec.whatwg.org/multipage/window-object.html#window</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-window">2.7. Classes should have constructors when possible</a>
    <li><a href="#ref-for-window①">3.4. Always add event handler attributes</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-windoweventhandlers">
   <a href="https://html.spec.whatwg.org/multipage/webappapis.html#windoweventhandlers">https://html.spec.whatwg.org/multipage/webappapis.html#windoweventhandlers</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-windoweventhandlers">3.4. Always add event handler attributes</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-browsing-context">
   <a href="https://html.spec.whatwg.org/multipage/browsers.html#browsing-context">https://html.spec.whatwg.org/multipage/browsers.html#browsing-context</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-browsing-context">4.3. Use the appropriate type to represent times and dates</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-createimagebitmap">
   <a href="https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#dom-createimagebitmap">https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#dom-createimagebitmap</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-createimagebitmap">2.7. Classes should have constructors when possible</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-custom-element">
   <a href="https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element">https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-custom-element">2.7. Classes should have constructors when possible</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-customized-built-in-element">
   <a href="https://html.spec.whatwg.org/multipage/custom-elements.html#customized-built-in-element">https://html.spec.whatwg.org/multipage/custom-elements.html#customized-built-in-element</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-customized-built-in-element">2.7. Classes should have constructors when possible</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-event-handler-idl-attributes">
   <a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-idl-attributes">https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-idl-attributes</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-event-handler-idl-attributes">3.4. Always add event handler attributes</a> <a href="#ref-for-event-handler-idl-attributes①">(2)</a> <a href="#ref-for-event-handler-idl-attributes②">(3)</a> <a href="#ref-for-event-handler-idl-attributes③">(4)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-the-img-element">
   <a href="https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element">https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-the-img-element">2.5. Use casing rules consistent with existing APIs</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-in-parallel">
   <a href="https://html.spec.whatwg.org/multipage/infrastructure.html#in-parallel">https://html.spec.whatwg.org/multipage/infrastructure.html#in-parallel</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-in-parallel">1.2. Preserve run-to-completion semantics</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-img-ismap">
   <a href="https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-ismap">https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-ismap</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-img-ismap">2.5. Use casing rules consistent with existing APIs</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-attr-img-ismap">
   <a href="https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-ismap">https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-ismap</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-attr-img-ismap">2.5. Use casing rules consistent with existing APIs</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dom-open">
   <a href="https://html.spec.whatwg.org/multipage/window-object.html#dom-open">https://html.spec.whatwg.org/multipage/window-object.html#dom-open</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dom-open">2.7. Classes should have constructors when possible</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-queue-a-task">
   <a href="https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-task">https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-task</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-queue-a-task">1.2. Preserve run-to-completion semantics</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-reflect">
   <a href="https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflect">https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflect</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-reflect">2.5. Use casing rules consistent with existing APIs</a> <a href="#ref-for-reflect①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-idbdatabase">
   <a href="https://w3c.github.io/IndexedDB/#idbdatabase">https://w3c.github.io/IndexedDB/#idbdatabase</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-idbdatabase">3.8. How to decide between Events and Observers</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-selector-combinator">
   <a href="https://drafts.csswg.org/selectors-4/#selector-combinator">https://drafts.csswg.org/selectors-4/#selector-combinator</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-selector-combinator">7.2. Specify clearly enough so that algorithms are unambiguous</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-mouseevent">
   <a href="https://www.w3.org/TR/uievents/#mouseevent">https://www.w3.org/TR/uievents/#mouseevent</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-mouseevent">2.7. Classes should have constructors when possible</a> <a href="#ref-for-mouseevent①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-urlsearchparams">
   <a href="https://url.spec.whatwg.org/#urlsearchparams">https://url.spec.whatwg.org/#urlsearchparams</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-urlsearchparams">2.4. Consider whether objects should be live or static</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-Constructor">
   <a href="https://heycam.github.io/webidl/#Constructor">https://heycam.github.io/webidl/#Constructor</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-Constructor">2.7. Classes should have constructors when possible</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-idl-DOMException">
   <a href="https://heycam.github.io/webidl/#idl-DOMException">https://heycam.github.io/webidl/#idl-DOMException</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-idl-DOMException">4.4. Use Error or DOMException for errors</a> <a href="#ref-for-idl-DOMException①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-DOMTimeStamp">
   <a href="https://heycam.github.io/webidl/#DOMTimeStamp">https://heycam.github.io/webidl/#DOMTimeStamp</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-DOMTimeStamp">4.3. Use the appropriate type to represent times and dates</a> <a href="#ref-for-DOMTimeStamp①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-exceptiondef-typeerror">
   <a href="https://heycam.github.io/webidl/#exceptiondef-typeerror">https://heycam.github.io/webidl/#exceptiondef-typeerror</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-exceptiondef-typeerror">2.7. Classes should have constructors when possible</a> <a href="#ref-for-exceptiondef-typeerror①">(2)</a>
    <li><a href="#ref-for-exceptiondef-typeerror②">4.4. Use Error or DOMException for errors</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dfn-maplike">
   <a href="https://heycam.github.io/webidl/#dfn-maplike">https://heycam.github.io/webidl/#dfn-maplike</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dfn-maplike">2.4. Consider whether objects should be live or static</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dfn-namespace">
   <a href="https://heycam.github.io/webidl/#dfn-namespace">https://heycam.github.io/webidl/#dfn-namespace</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dfn-namespace">2.7. Classes should have constructors when possible</a> <a href="#ref-for-dfn-namespace①">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-dfn-setlike">
   <a href="https://heycam.github.io/webidl/#dfn-setlike">https://heycam.github.io/webidl/#dfn-setlike</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-dfn-setlike">2.4. Consider whether objects should be live or static</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-xmlhttprequest">
   <a href="https://xhr.spec.whatwg.org/#xmlhttprequest">https://xhr.spec.whatwg.org/#xmlhttprequest</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-xmlhttprequest">2.5. Use casing rules consistent with existing APIs</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-xmlhttprequesteventtarget">
   <a href="https://xhr.spec.whatwg.org/#xmlhttprequesteventtarget">https://xhr.spec.whatwg.org/#xmlhttprequesteventtarget</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-xmlhttprequesteventtarget">3.8. How to decide between Events and Observers</a>
   </ul>
  </aside>
  <h3 class="no-num no-ref heading settled" id="index-defined-elsewhere"><span class="content">Terms defined by reference</span><a class="self-link" href="#index-defined-elsewhere"></a></h3>
  <ul class="index">
   <li>
    <a data-link-type="biblio">[css-conditional-3]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-at-ruledef-supports" style="color:initial">@supports</span>
    </ul>
   <li>
    <a data-link-type="biblio">[cssom-1]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-dom-window-getcomputedstyle" style="color:initial">getComputedStyle(elt)</span>
    </ul>
   <li>
    <a data-link-type="biblio">[DOM]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-domerror" style="color:initial">DOMError</span>
     <li><span class="dfn-paneled" id="term-for-domtokenlist" style="color:initial">DOMTokenList</span>
     <li><span class="dfn-paneled" id="term-for-element" style="color:initial">Element</span>
     <li><span class="dfn-paneled" id="term-for-event" style="color:initial">Event</span>
     <li><span class="dfn-paneled" id="term-for-eventtarget" style="color:initial">EventTarget</span>
     <li><span class="dfn-paneled" id="term-for-htmlcollection" style="color:initial">HTMLCollection</span>
     <li><span class="dfn-paneled" id="term-for-mutationobserver" style="color:initial">MutationObserver</span>
     <li><span class="dfn-paneled" id="term-for-dictdef-mutationobserverinit" style="color:initial">MutationObserverInit</span>
     <li><span class="dfn-paneled" id="term-for-mutationrecord" style="color:initial">MutationRecord</span>
     <li><span class="dfn-paneled" id="term-for-node" style="color:initial">Node</span>
     <li><span class="dfn-paneled" id="term-for-nodelist" style="color:initial">NodeList</span>
     <li><span class="dfn-paneled" id="term-for-dom-eventtarget-addeventlistener" style="color:initial">addEventListener(type, callback)</span>
     <li><span class="dfn-paneled" id="term-for-dom-eventtarget-dispatchevent" style="color:initial">dispatchEvent(event)</span>
     <li><span class="dfn-paneled" id="term-for-dom-document-getelementsbytagname" style="color:initial">getElementsByTagName(qualifiedName)</span>
     <li><span class="dfn-paneled" id="term-for-dom-addeventlisteneroptions-once" style="color:initial">once</span>
     <li><span class="dfn-paneled" id="term-for-dom-parentnode-queryselectorall" style="color:initial">querySelectorAll(selectors)</span>
     <li><span class="dfn-paneled" id="term-for-dom-event-target" style="color:initial">target</span>
    </ul>
   <li>
    <a data-link-type="biblio">[HIGHRES-TIME]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-dom-domhighrestimestamp" style="color:initial">DOMHighResTimeStamp</span>
    </ul>
   <li>
    <a data-link-type="biblio">[HTML]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-globaleventhandlers" style="color:initial">GlobalEventHandlers</span>
     <li><span class="dfn-paneled" id="term-for-htmlconstructor" style="color:initial">HTMLConstructor</span>
     <li><span class="dfn-paneled" id="term-for-htmlhtmlelement" style="color:initial">HTMLHtmlElement</span>
     <li><span class="dfn-paneled" id="term-for-htmlimageelement" style="color:initial">HTMLImageElement</span>
     <li><span class="dfn-paneled" id="term-for-history-3" style="color:initial">History</span>
     <li><span class="dfn-paneled" id="term-for-imagebitmap" style="color:initial">ImageBitmap</span>
     <li><span class="dfn-paneled" id="term-for-navigator" style="color:initial">Navigator</span>
     <li><span class="dfn-paneled" id="term-for-window" style="color:initial">Window</span>
     <li><span class="dfn-paneled" id="term-for-windoweventhandlers" style="color:initial">WindowEventHandlers</span>
     <li><span class="dfn-paneled" id="term-for-browsing-context" style="color:initial">browsing context</span>
     <li><span class="dfn-paneled" id="term-for-dom-createimagebitmap" style="color:initial">createImageBitmap(image)</span>
     <li><span class="dfn-paneled" id="term-for-custom-element" style="color:initial">custom element</span>
     <li><span class="dfn-paneled" id="term-for-customized-built-in-element" style="color:initial">customized built-in element</span>
     <li><span class="dfn-paneled" id="term-for-event-handler-idl-attributes" style="color:initial">event handler idl attribute</span>
     <li><span class="dfn-paneled" id="term-for-the-img-element" style="color:initial">img</span>
     <li><span class="dfn-paneled" id="term-for-in-parallel" style="color:initial">in parallel</span>
     <li><span class="dfn-paneled" id="term-for-dom-img-ismap" style="color:initial">isMap</span>
     <li><span class="dfn-paneled" id="term-for-attr-img-ismap" style="color:initial">ismap</span>
     <li><span class="dfn-paneled" id="term-for-dom-open" style="color:initial">open()</span>
     <li><span class="dfn-paneled" id="term-for-queue-a-task" style="color:initial">queue a task</span>
     <li><span class="dfn-paneled" id="term-for-reflect" style="color:initial">reflect</span>
    </ul>
   <li>
    <a data-link-type="biblio">[IndexedDB-2]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-idbdatabase" style="color:initial">IDBDatabase</span>
    </ul>
   <li>
    <a data-link-type="biblio">[selectors-4]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-selector-combinator" style="color:initial">combinator</span>
    </ul>
   <li>
    <a data-link-type="biblio">[uievents]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-mouseevent" style="color:initial">MouseEvent</span>
    </ul>
   <li>
    <a data-link-type="biblio">[URL]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-urlsearchparams" style="color:initial">URLSearchParams</span>
    </ul>
   <li>
    <a data-link-type="biblio">[WEBIDL]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-Constructor" style="color:initial">Constructor</span>
     <li><span class="dfn-paneled" id="term-for-idl-DOMException" style="color:initial">DOMException</span>
     <li><span class="dfn-paneled" id="term-for-DOMTimeStamp" style="color:initial">DOMTimeStamp</span>
     <li><span class="dfn-paneled" id="term-for-exceptiondef-typeerror" style="color:initial">TypeError</span>
     <li><span class="dfn-paneled" id="term-for-dfn-maplike" style="color:initial">maplike</span>
     <li><span class="dfn-paneled" id="term-for-dfn-namespace" style="color:initial">namespace</span>
     <li><span class="dfn-paneled" id="term-for-dfn-setlike" style="color:initial">setlike</span>
    </ul>
   <li>
    <a data-link-type="biblio">[XHR]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-xmlhttprequest" style="color:initial">XMLHttpRequest</span>
     <li><span class="dfn-paneled" id="term-for-xmlhttprequesteventtarget" style="color:initial">XMLHttpRequestEventTarget</span>
    </ul>
  </ul>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="normative"><span class="content">Normative References</span><a class="self-link" href="#normative"></a></h3>
  <dl>
   <dt id="biblio-css-conditional-3">[CSS-CONDITIONAL-3]
   <dd>CSS Conditional Rules Module Level 3 URL: <a href="https://drafts.csswg.org/css-conditional-3/">https://drafts.csswg.org/css-conditional-3/</a>
   <dt id="biblio-cssom-1">[CSSOM-1]
   <dd>Simon Pieters; Glenn Adams. <a href="https://drafts.csswg.org/cssom/">CSS Object Model (CSSOM)</a>. URL: <a href="https://drafts.csswg.org/cssom/">https://drafts.csswg.org/cssom/</a>
   <dt id="biblio-dom">[DOM]
   <dd>Anne van Kesteren. <a href="https://dom.spec.whatwg.org/">DOM Standard</a>. Living Standard. URL: <a href="https://dom.spec.whatwg.org/">https://dom.spec.whatwg.org/</a>
   <dt id="biblio-ecmascript">[ECMASCRIPT]
   <dd><a href="https://tc39.github.io/ecma262/">ECMAScript Language Specification</a>. URL: <a href="https://tc39.github.io/ecma262/">https://tc39.github.io/ecma262/</a>
   <dt id="biblio-highres-time">[HIGHRES-TIME]
   <dd>Ilya Grigorik; James Simonsen; Jatinder Mann. <a href="https://w3c.github.io/hr-time/">High Resolution Time Level 2</a>. URL: <a href="https://w3c.github.io/hr-time/">https://w3c.github.io/hr-time/</a>
   <dt id="biblio-html">[HTML]
   <dd>Anne van Kesteren; et al. <a href="https://html.spec.whatwg.org/multipage/">HTML Standard</a>. Living Standard. URL: <a href="https://html.spec.whatwg.org/multipage/">https://html.spec.whatwg.org/multipage/</a>
   <dt id="biblio-indexeddb-2">[IndexedDB-2]
   <dd>Ali Alabbas; Joshua Bell. <a href="https://w3c.github.io/IndexedDB/">Indexed Database API 2.0</a>. URL: <a href="https://w3c.github.io/IndexedDB/">https://w3c.github.io/IndexedDB/</a>
   <dt id="biblio-rfc2119">[RFC2119]
   <dd>S. Bradner. <a href="https://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a>. March 1997. Best Current Practice. URL: <a href="https://tools.ietf.org/html/rfc2119">https://tools.ietf.org/html/rfc2119</a>
   <dt id="biblio-selectors-4">[SELECTORS-4]
   <dd>Elika Etemad; Tab Atkins Jr.. <a href="https://drafts.csswg.org/selectors/">Selectors Level 4</a>. URL: <a href="https://drafts.csswg.org/selectors/">https://drafts.csswg.org/selectors/</a>
   <dt id="biblio-url">[URL]
   <dd>Anne van Kesteren. <a href="https://url.spec.whatwg.org/">URL Standard</a>. Living Standard. URL: <a href="https://url.spec.whatwg.org/">https://url.spec.whatwg.org/</a>
   <dt id="biblio-webidl">[WEBIDL]
   <dd>Boris Zbarsky. <a href="https://heycam.github.io/webidl/">Web IDL</a>. URL: <a href="https://heycam.github.io/webidl/">https://heycam.github.io/webidl/</a>
   <dt id="biblio-xhr">[XHR]
   <dd>Anne van Kesteren. <a href="https://xhr.spec.whatwg.org/">XMLHttpRequest Standard</a>. Living Standard. URL: <a href="https://xhr.spec.whatwg.org/">https://xhr.spec.whatwg.org/</a>
  </dl>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-uievents">[UIEVENTS]
   <dd>Gary Kacmarcik; Travis Leithead; Doug Schepers. <a href="https://w3c.github.io/uievents/">UI Events</a>. URL: <a href="https://w3c.github.io/uievents/">https://w3c.github.io/uievents/</a>
  </dl>
<script>/* script-dfn-panel */

document.body.addEventListener("click", function(e) {
    var queryAll = function(sel) { return [].slice.call(document.querySelectorAll(sel)); }
    // Find the dfn element or panel, if any, that was clicked on.
    var el = e.target;
    var target;
    var hitALink = false;
    while(el.parentElement) {
        if(el.tagName == "A") {
            // Clicking on a link in a <dfn> shouldn't summon the panel
            hitALink = true;
        }
        if(el.classList.contains("dfn-paneled")) {
            target = "dfn";
            break;
        }
        if(el.classList.contains("dfn-panel")) {
            target = "dfn-panel";
            break;
        }
        el = el.parentElement;
    }
    if(target != "dfn-panel") {
        // Turn off any currently "on" or "activated" panels.
        queryAll(".dfn-panel.on, .dfn-panel.activated").forEach(function(el){
            el.classList.remove("on");
            el.classList.remove("activated");
        });
    }
    if(target == "dfn" && !hitALink) {
        // open the panel
        var dfnPanel = document.querySelector(".dfn-panel[data-for='" + el.id + "']");
        if(dfnPanel) {
            dfnPanel.classList.add("on");
            var rect = el.getBoundingClientRect();
            dfnPanel.style.left = window.scrollX + rect.right + 5 + "px";
            dfnPanel.style.top = window.scrollY + rect.top + "px";
            var panelRect = dfnPanel.getBoundingClientRect();
            var panelWidth = panelRect.right - panelRect.left;
            if(panelRect.right > document.body.scrollWidth && (rect.left - (panelWidth + 5)) > 0) {
                // Reposition, because the panel is overflowing
                dfnPanel.style.left = window.scrollX + rect.left - (panelWidth + 5) + "px";
            }
        } else {
            console.log("Couldn't find .dfn-panel[data-for='" + el.id + "']");
        }
    } else if(target == "dfn-panel") {
        // Switch it to "activated" state, which pins it.
        el.classList.add("activated");
        el.style.left = null;
        el.style.top = null;
    }

});
</script>